Compare commits
No commits in common. "3d8047c01c67acd4f821253f1883c41a3b920e99" and "0fcda98b9fcab457f9eaa23003f30d21e1df66bd" have entirely different histories.
3d8047c01c
...
0fcda98b9f
47 changed files with 345 additions and 618 deletions
|
@ -25,18 +25,6 @@ namespace Neighbourhood.omg.lol
|
|||
AddToken(token);
|
||||
}
|
||||
|
||||
public T? Deserialize<T>(string str) {
|
||||
T? responseObj = default(T);
|
||||
try {
|
||||
responseObj = JsonSerializer.Deserialize<T>(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);
|
||||
|
@ -54,8 +42,8 @@ namespace Neighbourhood.omg.lol
|
|||
string str = await response.Content.ReadAsStringAsync();
|
||||
try {
|
||||
OmgLolResponse<T>? responseObj = await response.Content.ReadFromJsonAsync<OmgLolResponse<T>>(_serializerOptions, cancellationToken: cancellationToken);
|
||||
if (responseObj?.Request == null || (responseObj?.Request?.Success ?? false)) {
|
||||
responseData = responseObj!.Response;
|
||||
if (responseObj?.Request?.Success ?? false) {
|
||||
responseData = responseObj.Response;
|
||||
}
|
||||
}
|
||||
catch (JsonException ex) {
|
||||
|
@ -90,81 +78,6 @@ namespace Neighbourhood.omg.lol
|
|||
return responseData;
|
||||
}
|
||||
|
||||
private async Task<TResponse?> PostBinary<TResponse, TData>(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<TResponse>? responseObj = await response.Content.ReadFromJsonAsync<OmgLolResponse<TResponse>>(_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<TResponse?> PostMultipart<TResponse, TData>(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<TResponse, TData>(uri, data: data, fileStream: fileStream, fileName: fileResult.FileName, contentType: fileResult.ContentType);
|
||||
}
|
||||
else return await PostMultipart<TResponse, TData>(uri, data, fileStream: null);
|
||||
}
|
||||
|
||||
private async Task<TResponse?> PostMultipart<TResponse, TData>(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<TResponse>? responseObj = await response.Content.ReadFromJsonAsync<OmgLolResponse<TResponse>>(_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<TResponse?> Put<TResponse, TData>(string uri, TData data, CancellationToken cancellationToken = default) where TResponse : IOmgLolResponseData {
|
||||
TResponse? responseData = default(TResponse);
|
||||
try {
|
||||
|
@ -318,14 +231,24 @@ namespace Neighbourhood.omg.lol
|
|||
|
||||
public async Task<BasicResponseData?> PostProfile(string address, PostProfile data) =>
|
||||
await Post<BasicResponseData, PostProfile>($"/address/{address}/web", data);
|
||||
public async Task<Dictionary<string, Theme>?> GetThemes() =>
|
||||
(await Get<ThemeResponseData>($"/theme/list"))?.Themes;
|
||||
|
||||
public async Task<MarkupString?> GetThemePreview(string theme) =>
|
||||
(MarkupString)((await Get<ThemePreviewResponseData>($"/theme/{theme}/preview"))?.Html ?? string.Empty);
|
||||
|
||||
public async Task<BasicResponseData?> PostProfilePic(string address, FileResult image) =>
|
||||
await PostBinary<BasicResponseData, object>($"/address/{address}/pfp", fileResult: image);
|
||||
public async Task<List<MarkupString>> EphemeralScrape() {
|
||||
List<string> notes = new List<string>();
|
||||
Uri Uri = new Uri($"https://eph.emer.al/");
|
||||
try {
|
||||
var response = await _client.GetAsync(Uri);
|
||||
var str = await response.Content.ReadAsStringAsync();
|
||||
string pattern = @"<p class=""post"">(.*?)<\/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<string?> OAuth(string code, string client_id, string client_secret, string redirect_uri) {
|
||||
string? token = null;
|
||||
|
|
|
@ -26,8 +26,6 @@ namespace Neighbourhood.omg.lol {
|
|||
|
||||
public List<StatusOrPic>? Feed { get; set; }
|
||||
|
||||
public Dictionary<string, Theme>? Themes { get; set; }
|
||||
|
||||
// Account data
|
||||
private AccountResponseData? _accountInfo;
|
||||
public AccountResponseData? AccountInfo {
|
||||
|
@ -307,12 +305,5 @@ namespace Neighbourhood.omg.lol {
|
|||
return Feed.OrderByDescending(s => s.CreatedTime);
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, Theme>?> GetThemes(bool forceRefresh = false) {
|
||||
if (forceRefresh || this.Themes == null || this.Themes.Count == 0) {
|
||||
this.Themes = await api.GetThemes();
|
||||
}
|
||||
return this.Themes;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
@inject IJSRuntime JS
|
||||
@inject State State
|
||||
@inject RestService api
|
||||
@inject NavigationManager navigationManager
|
||||
|
||||
<div class="overlay @(Active ? "active" : string.Empty)" data-ui="#@id"></div>
|
||||
<dialog id="@id" class="@(Active ? "active" : string.Empty)" open="@Active">
|
||||
<h5>Update your profile picture</h5>
|
||||
<div class="padding center-align">
|
||||
<img src="@(Base64Url ?? ExistingUrl)" class="small-height square" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<button @onclick="PicFromMedia"><i class="fa-solid fa-image"></i> Select a picture</button>
|
||||
<button @onclick="PicFromPhoto"><i class="fa-solid fa-camera"></i> Take a photo</button>
|
||||
</div>
|
||||
<nav class="right-align no-space">
|
||||
<button class="transparent link" data-ui="#@id" disabled="@loading">Cancel</button>
|
||||
<button @onclick="PostPic" disabled="@loading">
|
||||
@if (loading) {
|
||||
<span>Uploading...</span>
|
||||
}
|
||||
else {
|
||||
<i class="fa-solid fa-cloud-arrow-up"></i> <span>Upload</span>
|
||||
}
|
||||
</button>
|
||||
</nav>
|
||||
</dialog>
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,8 +10,6 @@
|
|||
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) {
|
||||
|
@ -23,18 +21,11 @@
|
|||
public async Task Reload() {
|
||||
if (Url != null){
|
||||
Html = await api.GetHtml(Url);
|
||||
SrcString = Html?.ToString();
|
||||
}
|
||||
if(SrcString != null) {
|
||||
SrcString = SrcString?.Replace("</head>", "<base target='_blank'></head>");
|
||||
SrcString = SrcString?.Replace("</body>", "<script src='https://cdn.jsdelivr.net/npm/@iframe-resizer/child'></script></body>");
|
||||
Html = (MarkupString)(SrcString ?? string.Empty);
|
||||
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 ?? string.Empty);
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await IframeResize();
|
||||
}
|
||||
|
||||
public async Task IframeResize() {
|
||||
await JS.InvokeVoidAsync("iframeResize", new { license = "GPLv3" });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
<div class="row">
|
||||
<button @onclick="PicFromMedia"><i class="fa-solid fa-image"></i> Select a picture</button>
|
||||
<button @onclick="PicFromPhoto"><i class="fa-solid fa-camera"></i> Take a photo</button>
|
||||
@* <div class="field label prefix border">
|
||||
<i class="fa-solid fa-image"></i>
|
||||
<InputFile OnChange="@ChangeFile" accept="image/gif, image/heic, image/heif, image/jpeg, image/png, image/svg+xml, image/webp"></InputFile>
|
||||
<input type="text">
|
||||
<label>Select a picture</label>
|
||||
</div> *@
|
||||
</div>
|
||||
<div class="row">
|
||||
@if(Base64File != null && FileSize != null){
|
||||
|
|
|
@ -2,32 +2,14 @@
|
|||
@inject NavigationManager Nav
|
||||
@inject RestService api
|
||||
@inject State State
|
||||
@inject IJSRuntime JS
|
||||
|
||||
|
||||
<div class="max markdown-editor">
|
||||
@if (markdownValue != null)
|
||||
{
|
||||
<MarkdownEditor @ref="Editor"
|
||||
@bind-Value="@markdownValue"
|
||||
Theme="material-darker"
|
||||
MaxHeight="100%"
|
||||
CustomButtonClicked="@OnCustomButtonClicked">
|
||||
<Toolbar>
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Bold" Icon="fa-solid fa-bold" Title="Bold" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Italic" Icon="fa-solid fa-italic" Title="Italic" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Heading" Icon="fa-solid fa-heading" Title="Heading" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Code" Icon="fa-solid fa-code" Title="Code" Separator="true" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Quote" Icon="fa-solid fa-quote-left" Title="Quote" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.UnorderedList" Icon="fa-solid fa-list-ul" Title="Unordered List" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.OrderedList" Icon="fa-solid fa-list-ol" Title="Ordered List" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Link" Icon="fa-solid fa-link" Title="Link" Separator="true" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Image" Icon="fa-solid fa-image" Title="Image" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.HorizontalRule" Icon="fa-solid fa-horizontal-rule" Title="Horizontal Rule" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Guide" Icon="fa-solid fa-circle-question" Title="Guide" Separator="true" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Custom" Icon="omg-icon omg-prami" Title="Editor Information" Name="Help" />
|
||||
</Toolbar>
|
||||
</MarkdownEditor>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
|
@ -52,7 +34,7 @@
|
|||
private bool listed;
|
||||
private string? markdownValue;
|
||||
|
||||
private bool loading = true;
|
||||
private bool loading = false;
|
||||
|
||||
protected override async Task OnInitializedAsync() {
|
||||
await base.OnInitializedAsync();
|
||||
|
@ -61,13 +43,8 @@
|
|||
{
|
||||
listed = data.Listed == 1;
|
||||
markdownValue = data.Content;
|
||||
|
||||
loading = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
await Editor!.SetValueAsync(markdownValue);
|
||||
}
|
||||
loading = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
|
@ -87,10 +64,4 @@
|
|||
|
||||
loading = false;
|
||||
}
|
||||
|
||||
public async Task OnCustomButtonClicked(MarkdownButtonEventArgs eventArgs) {
|
||||
if (eventArgs.Name == "Help") {
|
||||
await JS.InvokeVoidAsync("open", "https://home.omg.lol/info/editor", "_blank");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
@inject State State
|
||||
@inject IJSRuntime JS
|
||||
|
||||
|
||||
<div class="max markdown-editor">
|
||||
@if (markdownValue != null)
|
||||
{
|
||||
<MarkdownEditor @ref="Editor"
|
||||
@bind-Value="@markdownValue"
|
||||
Theme="material-darker"
|
||||
|
@ -24,27 +23,15 @@
|
|||
<MarkdownToolbarButton Action="MarkdownAction.Image" Icon="fa-solid fa-image" Title="Image" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.HorizontalRule" Icon="fa-solid fa-horizontal-rule" Title="Horizontal Rule" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Guide" Icon="fa-solid fa-circle-question" Title="Guide" Separator="true" />
|
||||
<MarkdownToolbarButton Action="MarkdownAction.Custom" Icon="omg-icon omg-prami" Title="Editor Information" Name="Help" />
|
||||
<MarkdownToolbarButton Name="Help" Action="MarkdownAction.Custom"
|
||||
Icon="omg-icon omg-prami"
|
||||
Title="Editor Information" />
|
||||
</Toolbar>
|
||||
</MarkdownEditor>
|
||||
}
|
||||
</div>
|
||||
@if (markdownValue != null)
|
||||
{
|
||||
<details id="advanced">
|
||||
|
||||
<details id="advanced">
|
||||
<summary> Advanced </summary>
|
||||
<h5>Theme:</h5>
|
||||
<div class="row bottom-margin">
|
||||
<ThemeDialog id="theme-modal" onthemechanged="ThemeChanged"></ThemeDialog>
|
||||
<a data-ui="#theme-modal" class="row min" style="text-decoration:none;">
|
||||
@if(selectedTheme != null) {
|
||||
<ThemeCard theme="selectedTheme"></ThemeCard>
|
||||
}
|
||||
else {
|
||||
<button>Choose a theme</button>
|
||||
}
|
||||
</a>
|
||||
</div>
|
||||
<small>Style you include here will be places in a <style> element in your page’s <head>.</small>
|
||||
<div class="field textarea label border max">
|
||||
<InputTextArea @bind-Value="css"></InputTextArea>
|
||||
|
@ -55,8 +42,8 @@
|
|||
<InputTextArea @bind-Value="head"></InputTextArea>
|
||||
<label>Additional <head> Content</label>
|
||||
</div>
|
||||
</details>
|
||||
}
|
||||
</details>
|
||||
|
||||
<nav>
|
||||
<div class="max"></div>
|
||||
<button class="transparent link" onclick="history.back();" disabled="@loading">Cancel</button>
|
||||
|
@ -75,11 +62,8 @@
|
|||
private string? markdownValue;
|
||||
private string? css;
|
||||
private string? head;
|
||||
private string? theme;
|
||||
private Theme? selectedTheme;
|
||||
private Dictionary<string, Theme>? themes;
|
||||
|
||||
private bool loading = true;
|
||||
private bool loading = false;
|
||||
|
||||
protected override async Task OnInitializedAsync() {
|
||||
await base.OnInitializedAsync();
|
||||
|
@ -88,17 +72,9 @@
|
|||
markdownValue = data.Content;
|
||||
css = data.Css;
|
||||
head = data.Head;
|
||||
theme = data.Theme;
|
||||
|
||||
themes = await State.GetThemes();
|
||||
selectedTheme = themes?[theme];
|
||||
|
||||
loading = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
await Editor!.SetValueAsync(markdownValue);
|
||||
}
|
||||
loading = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
|
@ -113,8 +89,7 @@
|
|||
new PostProfile() {
|
||||
Content = markdownValue ?? string.Empty,
|
||||
Css = string.IsNullOrEmpty(css) ? null : css,
|
||||
Head = string.IsNullOrEmpty(head) ? null : head,
|
||||
Theme = string.IsNullOrEmpty(theme) ? null : theme
|
||||
Head = string.IsNullOrEmpty(head) ? null : head
|
||||
});
|
||||
if (result != null) {
|
||||
await State.RefreshNow();
|
||||
|
@ -123,7 +98,6 @@
|
|||
}
|
||||
|
||||
loading = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
public async Task OnCustomButtonClicked(MarkdownButtonEventArgs eventArgs) {
|
||||
|
@ -131,10 +105,4 @@
|
|||
await JS.InvokeVoidAsync("open", "https://home.omg.lol/info/editor", "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
public void ThemeChanged(Theme? _theme) {
|
||||
theme = _theme?.Id;
|
||||
selectedTheme = _theme;
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,13 +9,7 @@
|
|||
<h3 class="page-heading"><i class="fa-solid fa-fw fa-at"></i>@Address</h3>
|
||||
</div>
|
||||
<div class="row center-align">
|
||||
<div class="min">
|
||||
@if (IsMe) {
|
||||
<EditProfilePicDialog id="profile-pic" Address="@Address"></EditProfilePicDialog>
|
||||
<button data-ui="#profile-pic" class="small circle small-elevate absolute top right no-margin" style="z-index:1;"><i class="fa-solid fa-pencil"></i></button>
|
||||
}
|
||||
<img class="profile avatar" src="https://profiles.cache.lol/@Address/picture" alt="@Address" />
|
||||
</div>
|
||||
</div>
|
||||
@if (FeatureFlags.Following) {
|
||||
<div class="row center-align">
|
||||
|
@ -82,7 +76,7 @@
|
|||
<StatusList @ref="StatusList" StatusFunc="@(async(refresh) => await State.GetStatuses(Address, refresh))" Editable="@IsMe"></StatusList>
|
||||
@if(IsMe) {
|
||||
<button class="fab circle extra large-elevate" data-ui="#post-modal">
|
||||
<i class="fa-solid fa-message-plus square"></i>
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</button>
|
||||
<NewStatusDialog id="post-modal"></NewStatusDialog>
|
||||
}
|
||||
|
@ -137,7 +131,7 @@
|
|||
private PicList? PicList { get; set; }
|
||||
|
||||
private bool IsMe {
|
||||
get => State.AddressList?.Any(a => a.Address == Address) ?? false;
|
||||
get => Address == State.SelectedAddressName;
|
||||
}
|
||||
|
||||
private MarkupString? bio;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<AuthorizeView>
|
||||
<Authorized>
|
||||
<button class="fab circle extra large-elevate" data-ui="#post-modal">
|
||||
<i class="fa-solid fa-message-plus square"></i>
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</button>
|
||||
<NewStatusDialog id="post-modal" Active="true" Content="@Text"></NewStatusDialog>
|
||||
</Authorized>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<AuthorizeView>
|
||||
<Authorized>
|
||||
<button class="fab circle extra large-elevate" data-ui="#post-modal">
|
||||
<i class="fa-solid fa-message-plus square"></i>
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</button>
|
||||
<NewStatusDialog id="post-modal"></NewStatusDialog>
|
||||
</Authorized>
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<article class="theme" style="@theme?.PreviewCssData?.BackgroundCss ; @theme?.PreviewCssData?.TextCss">
|
||||
<h5 class="address">@theme?.Name</h5>
|
||||
<p class="small theme-author" style="@theme?.PreviewCssData?.LinkCss">
|
||||
<i class="fa-solid fa-palette" style="@theme?.PreviewCssData?.IconCss"></i> by @theme?.Author
|
||||
</p>
|
||||
</article>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public Theme? theme { get; set; }
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
@inject IJSRuntime JS
|
||||
@inject State State
|
||||
@inject RestService api
|
||||
@inject NavigationManager navigationManager
|
||||
|
||||
<div class="overlay @(Active ? "active" : string.Empty)" data-ui="#@id"></div>
|
||||
<dialog id="@id" class="@(Active ? "active" : string.Empty)" open="@Active" style="overflow:auto;">
|
||||
<h5>Choose a theme</h5>
|
||||
<nav class="wrap max">
|
||||
@if(themes != null) foreach(Theme theme in themes.Values) {
|
||||
<a onclick="@(() => ClickTheme(theme))" class="min" style="text-decoration:none;">
|
||||
<ThemeCard theme="@theme"></ThemeCard>
|
||||
</a>
|
||||
}
|
||||
</nav>
|
||||
<nav class="right-align no-space">
|
||||
<button class="transparent link" data-ui="#@id">Cancel</button>
|
||||
</nav>
|
||||
</dialog>
|
||||
|
||||
<div class="overlay" data-ui="#@previewId"></div>
|
||||
<dialog id="@previewId" style="overflow:auto;">
|
||||
<h5 class="address">@activeTheme?.Name</h5>
|
||||
<div class="max">
|
||||
<p>@((MarkupString)(activeTheme?.Description ?? string.Empty)) A theme by <a href="@activeTheme?.AuthorUrl" target="_blank">@activeTheme?.Author</a>.</p>
|
||||
@if(themePreview != null) {
|
||||
<ExternalPageComponent id="profile_page" @ref="iframe" SrcString="@themePreview.ToString()"></ExternalPageComponent>
|
||||
}
|
||||
</div>
|
||||
<nav class="right-align no-space">
|
||||
<button class="transparent link" @onclick="CancelPreview">Back</button>
|
||||
<button @onclick=UseTheme><i class="fa-solid fa-palette"></i> Use the @activeTheme?.Name theme</button>
|
||||
</nav>
|
||||
</dialog>
|
||||
|
||||
@code {
|
||||
private Dictionary<string, Theme>? themes;
|
||||
[Parameter]
|
||||
public string? id { get; set; }
|
||||
private string? previewId { get => $"{id}-preview"; }
|
||||
[Parameter]
|
||||
public bool Active { get; set; }
|
||||
[Parameter]
|
||||
public Action<Theme?>? 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);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class AddressResponseData : IOmgLolResponseData {
|
||||
public string Address { get; set; } = string.Empty;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class AddressResponseList : List<AddressResponseData>, IOmgLolResponseList<AddressResponseData> {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class BasicResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class DirectoryResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public string Url { get; set; } = string.Empty;
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class EphemeralData {
|
||||
public string Content { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class EphemeralResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public List<string> Content { get; set; } = new List<string>();
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public interface IOmgLolResponseList<T> : IList<T>, IOmgLolResponseData where T : IOmgLolResponseData {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class NowContentData {
|
||||
public string? Content { get; set; }
|
||||
public long? Updated { get; set; }
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class NowPageResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public NowContentData? Now { get; set; }
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
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; } = string.Empty;
|
||||
public long Count { get; set; }
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class PatchStatus {
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string Content { get; set; } = string.Empty;
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class PatchStatusResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class PostPic {
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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; }
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,16 +1,21 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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; }
|
||||
public string? Head { get; set; }
|
||||
public short Verified { get; set; }
|
||||
public string Css { get; set; } = string.Empty;
|
||||
public string Head { get; set; } = string.Empty;
|
||||
public string Verified { get; set; } = string.Empty;
|
||||
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; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class PutPic {
|
||||
public string Pic { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class PutPicResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class SomePicsResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public List<Pic>? Pics { get; set; }
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class StatusBioResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public string Bio { get; set; } = string.Empty;
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class StatusPost {
|
||||
public string? Emoji { get; set; }
|
||||
public string? Content { get; set; }
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class StatusPostResponseData : IOmgLolResponseData {
|
||||
public string? Message { get; set; }
|
||||
public string? Id { get; set; }
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class StatusResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public List<Status> Statuses { get; set; } = new List<Status>();
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class ThemePreviewResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public string Html { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class ThemeResponseData : IOmgLolResponseData {
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public Dictionary<string, Theme> Themes { get; set; } = new Dictionary<string, Theme>();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Neighbourhood.omg.lol.Models {
|
||||
public class StatusOrPic {
|
||||
public Status? Status { get; set; }
|
||||
public Pic? Pic { get; set; }
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
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<PreviewCssData>(this.PreviewCss);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,10 @@
|
|||
namespace Neighbourhood.omg.lol.Models {
|
||||
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; }
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
|
||||
<!-- Images -->
|
||||
<MauiImage Include="Resources\Images\*" />
|
||||
<None Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />
|
||||
<MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />
|
||||
|
||||
<!-- Custom Fonts -->
|
||||
<MauiFont Include="Resources\Fonts\*" />
|
||||
|
@ -117,11 +117,22 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MauiAsset Remove="Resources\Raw\AboutAssets.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MauiImage Remove="Resources\Images\dotnet_bot.svg" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-brands-400.ttf" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-brands-400.woff2" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-duotone-900.ttf" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-duotone-900.woff2" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-light-300.ttf" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-light-300.woff2" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-regular-400.ttf" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-regular-400.woff2" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-solid-900.ttf" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-solid-900.woff2" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-thin-100.ttf" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-thin-100.woff2" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-v4compatibility.ttf" />
|
||||
<MauiFont Remove="Resources\Fonts\fa-v4compatibility.woff2" />
|
||||
<MauiFont Remove="Resources\Fonts\omg.lol-icons.woff2" />
|
||||
<MauiFont Remove="Resources\Fonts\seguiemj.ttf" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -143,6 +154,73 @@
|
|||
<None Remove="Resources\Fonts\seguiemj.ttf" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\Fonts\fa-brands-400.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-brands-400.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-duotone-900.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-duotone-900.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-light-300.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-light-300.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-regular-400.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-regular-400.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-solid-900.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-solid-900.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-thin-100.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-thin-100.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-v4compatibility.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\fa-v4compatibility.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\omg.lol-icons.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\Fonts\seguiemj.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="appsettings.json" />
|
||||
</ItemGroup>
|
||||
|
@ -162,73 +240,6 @@
|
|||
<PackageReference Include="PSC.Blazor.Components.MarkdownEditor" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MauiFont Update="Resources\Fonts\fa-brands-400.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-brands-400.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-duotone-900.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-duotone-900.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-light-300.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-light-300.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-regular-400.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-regular-400.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-solid-900.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-solid-900.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-thin-100.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-thin-100.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-v4compatibility.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\fa-v4compatibility.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\omg.lol-icons.woff2">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
<MauiFont Update="Resources\Fonts\seguiemj.ttf">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</MauiFont>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MauiXaml Update="XamlComponents\AppShell.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
@import url(../vendor/fluent-emoji/SegoeUIEmoji.css);
|
||||
/*@import url(../vendor/fluent-emoji/3d.css);*/
|
||||
@import url(../vendor/fluent-emoji/animated-optional.css);
|
||||
@import url(../vendor/TwemojiCountryFlags.css);
|
||||
@import url(../vendor/TossFaceEmojiFlags.css);
|
||||
|
||||
|
||||
:root {
|
||||
--emoji-font: TwemojiCountryFlags, SegoeUIEmoji, 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', 'Segoe UI Symbol';
|
||||
--emoji-font: TossFaceEmojiFlags, SegoeUIEmoji, 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', 'Segoe UI Symbol';
|
||||
--font: 'Lato', 'Helvetica Neue', Helvetica, Arial, sans-serif, var(--emoji-font);
|
||||
--prami-svg: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><path fill="%23FF6BAE" stroke="none" d="M250 450C211.612 450 173.225 435.354 143.934 406.066L43.9346 306.066C-14.6446 247.487 -14.6446 152.513 43.9346 93.9341C100.533 37.3361 191.104 35.421 250 88.1907C308.898 35.4229 399.47 37.3379 456.066 93.9341C514.645 152.513 514.645 247.487 456.066 306.066L356.066 406.066C326.778 435.354 288.389 450 250 450" /><path fill="none" stroke="%23471036" stroke-width="19" stroke-linecap="round" d="M208.749 223.817C227.625 254.619 272.376 254.619 291.251 223.817" /><circle fill="%23471036" cx="291.3" cy="176.6" r="17.75" /><circle fill="%23471036" cx="208.6" cy="176.6" r="17.75" /><circle fill="%23E24097" cx="120.3" cy="212" r="59.2" /><circle fill="%23E24097" cx="379.7" cy="212" r="59.2" /></svg>');
|
||||
--spacing: 1.5rem;
|
||||
|
@ -319,7 +319,7 @@ article.ephemeral {
|
|||
flex-direction:column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
iframe {
|
||||
#now.page > iframe {
|
||||
width:100%;
|
||||
flex-grow: 1;
|
||||
border: none;
|
||||
|
@ -502,8 +502,3 @@ article.now {
|
|||
color: #EEFFFF;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
article.theme {
|
||||
height: 10rem;
|
||||
width: 15rem;
|
||||
}
|
|
@ -29,19 +29,3 @@ function toggleDetails(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)
|
||||
})
|
||||
}
|
5
wwwroot/vendor/TossFaceEmojiFlags.css
vendored
Normal file
5
wwwroot/vendor/TossFaceEmojiFlags.css
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
@font-face {
|
||||
font-family: TossFaceEmojiFlags;
|
||||
src: url(TossFaceFontWeb.otf);
|
||||
unicode-range: U+1F1E6-1F1FF;
|
||||
}
|
BIN
wwwroot/vendor/TossFaceFontWeb.otf
vendored
Normal file
BIN
wwwroot/vendor/TossFaceFontWeb.otf
vendored
Normal file
Binary file not shown.
5
wwwroot/vendor/TwemojiCountryFlags.css
vendored
5
wwwroot/vendor/TwemojiCountryFlags.css
vendored
|
@ -1,5 +0,0 @@
|
|||
@font-face {
|
||||
font-family: TwemojiCountryFlags;
|
||||
src: url(TwemojiCountryFlags.woff2);
|
||||
unicode-range: U+1F1E6-1F1FF;
|
||||
}
|
BIN
wwwroot/vendor/TwemojiCountryFlags.woff2
vendored
BIN
wwwroot/vendor/TwemojiCountryFlags.woff2
vendored
Binary file not shown.
Loading…
Reference in a new issue