This commit is contained in:
Tyrrrz 2023-05-19 14:49:31 +03:00
parent 0ae9062a30
commit 03c5c1bc5e
5 changed files with 42 additions and 48 deletions

View file

@ -1,9 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AsyncKeyedLock" Version="6.2.1" /> <PackageReference Include="AsyncKeyedLock" Version="6.2.1" />
<PackageReference Include="Gress" Version="2.1.1" /> <PackageReference Include="Gress" Version="2.1.1" />

View file

@ -46,7 +46,7 @@
<div id="chatlog__message-container-@message.Id" class="chatlog__message-container @(message.IsPinned ? "chatlog__message-container--pinned" : null)" data-message-id="@message.Id"> <div id="chatlog__message-container-@message.Id" class="chatlog__message-container @(message.IsPinned ? "chatlog__message-container--pinned" : null)" data-message-id="@message.Id">
<div class="chatlog__message"> <div class="chatlog__message">
@{/* System notification */} @* System notification *@
@if (message.Kind.IsSystemNotification()) @if (message.Kind.IsSystemNotification())
{ {
<div class="chatlog__message-aside"> <div class="chatlog__message-aside">
@ -70,13 +70,13 @@
</div> </div>
<div class="chatlog__message-primary"> <div class="chatlog__message-primary">
@{/* Author name */} @* Author name *@
<span class="chatlog__system-notification-author" style="@(authorColor is not null ? $"color: rgb({authorColor.Value.R}, {authorColor.Value.G}, {authorColor.Value.B})" : null)" title="@message.Author.FullName" data-user-id="@message.Author.Id">@authorNick</span> <span class="chatlog__system-notification-author" style="@(authorColor is not null ? $"color: rgb({authorColor.Value.R}, {authorColor.Value.G}, {authorColor.Value.B})" : null)" title="@message.Author.FullName" data-user-id="@message.Author.Id">@authorNick</span>
@{/* Space out the content */} @* Space out the content *@
<span> </span> <span> </span>
@{/* System notification content */} @* System notification content *@
<span class="chatlog__system-notification-content"> <span class="chatlog__system-notification-content">
@if (message.Kind == MessageKind.RecipientAdd && message.MentionedUsers.Any()) @if (message.Kind == MessageKind.RecipientAdd && message.MentionedUsers.Any())
{ {
@ -130,7 +130,7 @@
} }
</span> </span>
@{/* Timestamp */} @* Timestamp *@
<span class="chatlog__system-notification-timestamp"> <span class="chatlog__system-notification-timestamp">
<a href="#chatlog__message-container-@message.Id">@FormatDate(message.Timestamp)</a> <a href="#chatlog__message-container-@message.Id">@FormatDate(message.Timestamp)</a>
</span> </span>
@ -222,10 +222,10 @@
// Header // Header
<div class="chatlog__header"> <div class="chatlog__header">
@{/* Author name */} @* Author name *@
<span class="chatlog__author" style="@(authorColor is not null ? $"color: rgb({authorColor.Value.R}, {authorColor.Value.G}, {authorColor.Value.B})" : null)" title="@message.Author.FullName" data-user-id="@message.Author.Id">@authorNick</span> <span class="chatlog__author" style="@(authorColor is not null ? $"color: rgb({authorColor.Value.R}, {authorColor.Value.G}, {authorColor.Value.B})" : null)" title="@message.Author.FullName" data-user-id="@message.Author.Id">@authorNick</span>
@{/* Bot tag */} @* Bot tag *@
@if (message.Author.IsBot) @if (message.Author.IsBot)
{ {
// For cross-posts, the BOT tag is replaced with the SERVER tag // For cross-posts, the BOT tag is replaced with the SERVER tag
@ -239,22 +239,22 @@
} }
} }
@{/* Timestamp */} @* Timestamp *@
<span class="chatlog__timestamp"><a href="#chatlog__message-container-@message.Id">@FormatDate(message.Timestamp)</a></span> <span class="chatlog__timestamp"><a href="#chatlog__message-container-@message.Id">@FormatDate(message.Timestamp)</a></span>
</div> </div>
} }
@{/* Content */} @* Content *@
@if ((!string.IsNullOrWhiteSpace(message.Content) && !message.IsContentHidden()) || message.EditedTimestamp is not null) @if ((!string.IsNullOrWhiteSpace(message.Content) && !message.IsContentHidden()) || message.EditedTimestamp is not null)
{ {
<div class="chatlog__content chatlog__markdown"> <div class="chatlog__content chatlog__markdown">
@{/* Text */} @* Text *@
@if (!string.IsNullOrWhiteSpace(message.Content) && !message.IsContentHidden()) @if (!string.IsNullOrWhiteSpace(message.Content) && !message.IsContentHidden())
{ {
<span class="chatlog__markdown-preserve"><!--wmm:ignore-->@Html.Raw(await FormatMarkdownAsync(message.Content))<!--/wmm:ignore--></span> <span class="chatlog__markdown-preserve"><!--wmm:ignore-->@Html.Raw(await FormatMarkdownAsync(message.Content))<!--/wmm:ignore--></span>
} }
@{/* Edited timestamp */} @* Edited timestamp *@
@if (message.EditedTimestamp is not null) @if (message.EditedTimestamp is not null)
{ {
<span class="chatlog__edited-timestamp" title="@FormatDate(message.EditedTimestamp.Value)">(edited)</span> <span class="chatlog__edited-timestamp" title="@FormatDate(message.EditedTimestamp.Value)">(edited)</span>
@ -262,17 +262,17 @@
</div> </div>
} }
@{/* Attachments */} @* Attachments *@
@foreach (var attachment in message.Attachments) @foreach (var attachment in message.Attachments)
{ {
<div class="chatlog__attachment @(attachment.IsSpoiler ? "chatlog__attachment--hidden" : null)" onclick="@(attachment.IsSpoiler ? "showSpoiler(event, this)" : null)"> <div class="chatlog__attachment @(attachment.IsSpoiler ? "chatlog__attachment--hidden" : null)" onclick="@(attachment.IsSpoiler ? "showSpoiler(event, this)" : null)">
@{/* Spoiler caption */} @* Spoiler caption *@
@if (attachment.IsSpoiler) @if (attachment.IsSpoiler)
{ {
<div class="chatlog__attachment-spoiler-caption">SPOILER</div> <div class="chatlog__attachment-spoiler-caption">SPOILER</div>
} }
@{/* Attachment preview */} @* Attachment preview *@
@if (attachment.IsImage) @if (attachment.IsImage)
{ {
<a href="@await ResolveAssetUrlAsync(attachment.Url)"> <a href="@await ResolveAssetUrlAsync(attachment.Url)">
@ -310,7 +310,7 @@
</div> </div>
} }
@{/* Invites */} @* Invites *@
@{ @{
var inviteCodes = MarkdownParser var inviteCodes = MarkdownParser
.ExtractLinks(message.Content) .ExtractLinks(message.Content)
@ -353,7 +353,7 @@
} }
} }
@{/* Embeds */} @* Embeds *@
@foreach (var embed in message.Embeds) @foreach (var embed in message.Embeds)
{ {
// Spotify embed // Spotify embed
@ -369,7 +369,7 @@
else if (embed.TryGetYouTubeVideo() is { } youTubeVideoEmbed) else if (embed.TryGetYouTubeVideo() is { } youTubeVideoEmbed)
{ {
<div class="chatlog__embed"> <div class="chatlog__embed">
@{/* Color pill */} @* Color pill *@
@if (embed.Color is not null) @if (embed.Color is not null)
{ {
<div class="chatlog__embed-color-pill" style="background-color: rgba(@embed.Color.Value.R, @embed.Color.Value.G, @embed.Color.Value.B, @embed.Color.Value.A)"></div> <div class="chatlog__embed-color-pill" style="background-color: rgba(@embed.Color.Value.R, @embed.Color.Value.G, @embed.Color.Value.B, @embed.Color.Value.A)"></div>
@ -382,7 +382,7 @@
<div class="chatlog__embed-content-container"> <div class="chatlog__embed-content-container">
<div class="chatlog__embed-content"> <div class="chatlog__embed-content">
<div class="chatlog__embed-text"> <div class="chatlog__embed-text">
@{/* Embed author */} @* Embed author *@
@if (embed.Author is not null) @if (embed.Author is not null)
{ {
<div class="chatlog__embed-author-container"> <div class="chatlog__embed-author-container">
@ -407,7 +407,7 @@
</div> </div>
} }
@{/* Embed title */} @* Embed title *@
@if (!string.IsNullOrWhiteSpace(embed.Title)) @if (!string.IsNullOrWhiteSpace(embed.Title))
{ {
<div class="chatlog__embed-title"> <div class="chatlog__embed-title">
@ -424,7 +424,7 @@
</div> </div>
} }
@{/* Video player */} @* Video player *@
<div class="chatlog__embed-youtube-container"> <div class="chatlog__embed-youtube-container">
<iframe class="chatlog__embed-youtube" src="@youTubeVideoEmbed.Url" width="400" height="225"></iframe> <iframe class="chatlog__embed-youtube" src="@youTubeVideoEmbed.Url" width="400" height="225"></iframe>
</div> </div>
@ -477,7 +477,7 @@
else else
{ {
<div class="chatlog__embed"> <div class="chatlog__embed">
@{/* Color pill */} @* Color pill *@
@if (embed.Color is not null) @if (embed.Color is not null)
{ {
<div class="chatlog__embed-color-pill" style="background-color: rgba(@embed.Color.Value.R, @embed.Color.Value.G, @embed.Color.Value.B, @embed.Color.Value.A)"></div> <div class="chatlog__embed-color-pill" style="background-color: rgba(@embed.Color.Value.R, @embed.Color.Value.G, @embed.Color.Value.B, @embed.Color.Value.A)"></div>
@ -490,7 +490,7 @@
<div class="chatlog__embed-content-container"> <div class="chatlog__embed-content-container">
<div class="chatlog__embed-content"> <div class="chatlog__embed-content">
<div class="chatlog__embed-text"> <div class="chatlog__embed-text">
@{/* Embed author */} @* Embed author *@
@if (embed.Author is not null) @if (embed.Author is not null)
{ {
<div class="chatlog__embed-author-container"> <div class="chatlog__embed-author-container">
@ -515,7 +515,7 @@
</div> </div>
} }
@{/* Embed title */} @* Embed title *@
@if (!string.IsNullOrWhiteSpace(embed.Title)) @if (!string.IsNullOrWhiteSpace(embed.Title))
{ {
<div class="chatlog__embed-title"> <div class="chatlog__embed-title">
@ -532,7 +532,7 @@
</div> </div>
} }
@{/* Embed description */} @* Embed description *@
@if (!string.IsNullOrWhiteSpace(embed.Description)) @if (!string.IsNullOrWhiteSpace(embed.Description))
{ {
<div class="chatlog__embed-description"> <div class="chatlog__embed-description">
@ -540,7 +540,7 @@
</div> </div>
} }
@{/* Embed fields */} @* Embed fields *@
@if (embed.Fields.Any()) @if (embed.Fields.Any())
{ {
<div class="chatlog__embed-fields"> <div class="chatlog__embed-fields">
@ -566,7 +566,7 @@
} }
</div> </div>
@{/* Embed content */} @* Embed content *@
@if (embed.Thumbnail is not null && !string.IsNullOrWhiteSpace(embed.Thumbnail.Url)) @if (embed.Thumbnail is not null && !string.IsNullOrWhiteSpace(embed.Thumbnail.Url))
{ {
<div class="chatlog__embed-thumbnail-container"> <div class="chatlog__embed-thumbnail-container">
@ -577,7 +577,7 @@
} }
</div> </div>
@{/* Embed images */} @* Embed images *@
@if (embed.Images.Any()) @if (embed.Images.Any())
{ {
<div class="chatlog__embed-images @(embed.Images.Count == 1 ? "chatlog__embed-images--single" : null)"> <div class="chatlog__embed-images @(embed.Images.Count == 1 ? "chatlog__embed-images--single" : null)">
@ -595,18 +595,18 @@
</div> </div>
} }
@{/* Embed footer & icon */} @* Embed footer & icon *@
@if (embed.Footer is not null || embed.Timestamp is not null) @if (embed.Footer is not null || embed.Timestamp is not null)
{ {
<div class="chatlog__embed-footer"> <div class="chatlog__embed-footer">
@{/* Footer icon */} @* Footer icon *@
@if (!string.IsNullOrWhiteSpace(embed.Footer?.IconUrl)) @if (!string.IsNullOrWhiteSpace(embed.Footer?.IconUrl))
{ {
<img class="chatlog__embed-footer-icon" src="@await ResolveAssetUrlAsync(embed.Footer.IconProxyUrl ?? embed.Footer.IconUrl)" alt="Footer icon" loading="lazy"> <img class="chatlog__embed-footer-icon" src="@await ResolveAssetUrlAsync(embed.Footer.IconProxyUrl ?? embed.Footer.IconUrl)" alt="Footer icon" loading="lazy">
} }
<span class="chatlog__embed-footer-text"> <span class="chatlog__embed-footer-text">
@{/* Footer text */} @* Footer text *@
@if (!string.IsNullOrWhiteSpace(embed.Footer?.Text)) @if (!string.IsNullOrWhiteSpace(embed.Footer?.Text))
{ {
@embed.Footer.Text @embed.Footer.Text
@ -617,7 +617,7 @@
@(" • ") @(" • ")
} }
@{/* Embed timestamp */} @* Embed timestamp *@
@if (embed.Timestamp is not null) @if (embed.Timestamp is not null)
{ {
@FormatDate(embed.Timestamp.Value) @FormatDate(embed.Timestamp.Value)
@ -630,7 +630,7 @@
} }
} }
@{/* Stickers */} @* Stickers *@
@foreach (var sticker in message.Stickers) @foreach (var sticker in message.Stickers)
{ {
<div class="chatlog__sticker" title="@sticker.Name"> <div class="chatlog__sticker" title="@sticker.Name">
@ -645,7 +645,7 @@
</div> </div>
} }
@{/* Message reactions */} @* Message reactions *@
@if (message.Reactions.Any()) @if (message.Reactions.Any())
{ {
<div class="chatlog__reactions"> <div class="chatlog__reactions">

View file

@ -38,7 +38,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
@{/* Styling */} @* Styling *@
<style> <style>
@@font-face { @@font-face {
src: url("@await ResolveAssetUrlAsync(GetFontUrl("normal", 400))"); src: url("@await ResolveAssetUrlAsync(GetFontUrl("normal", 400))");
@ -865,7 +865,7 @@
} }
</style> </style>
@{/* Syntax highlighting */} @* Syntax highlighting *@
<link rel="stylesheet" href="@await ResolveAssetUrlAsync($"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/solarized-{ThemeName.ToLowerInvariant()}.min.css")"> <link rel="stylesheet" href="@await ResolveAssetUrlAsync($"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/solarized-{ThemeName.ToLowerInvariant()}.min.css")">
<script src="@await ResolveAssetUrlAsync("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js")"></script> <script src="@await ResolveAssetUrlAsync("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js")"></script>
<script> <script>
@ -874,7 +874,7 @@
}); });
</script> </script>
@{/* Lottie animation support */} @* Lottie animation support *@
<script src="@await ResolveAssetUrlAsync("https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.8.1/lottie.min.js")"></script> <script src="@await ResolveAssetUrlAsync("https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.8.1/lottie.min.js")"></script>
<script> <script>
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
@ -895,7 +895,7 @@
}); });
</script> </script>
@{/* Scripts */} @* Scripts *@
<script> <script>
function scrollToMessage(event, id) { function scrollToMessage(event, id) {
const element = document.getElementById('chatlog__message-container-' + id); const element = document.getElementById('chatlog__message-container-' + id);
@ -932,7 +932,7 @@
} }
</script> </script>
@{/* Icons */} @* Icons *@
<svg style="display: none" xmlns="http://www.w3.org/2000/svg"> <svg style="display: none" xmlns="http://www.w3.org/2000/svg">
<defs> <defs>
<symbol id="attachment-icon" viewBox="0 0 720 960"> <symbol id="attachment-icon" viewBox="0 0 720 960">
@ -1001,7 +1001,7 @@
</div> </div>
</div> </div>
@{/* Preamble cuts off at this point */} @* Preamble cuts off at this point *@
<!--wmm:ignore--> <!--wmm:ignore-->
<div class="chatlog"> <div class="chatlog">
<!--/wmm:ignore--> <!--/wmm:ignore-->

View file

@ -42,7 +42,7 @@ public class MultiSelectionListBoxBehavior<T> : Behavior<ListBox>
set => SetValue(SelectedItemsProperty, value); set => SetValue(SelectedItemsProperty, value);
} }
// Propagate selected items from model to view // Propagate selected items from the model to the view
private void SelectItems() private void SelectItems()
{ {
_viewHandled = true; _viewHandled = true;
@ -57,7 +57,7 @@ public class MultiSelectionListBoxBehavior<T> : Behavior<ListBox>
_viewHandled = false; _viewHandled = false;
} }
// Propagate selected items from view to model // Propagate selected items from the view to the model
private void OnListBoxSelectionChanged(object? sender, SelectionChangedEventArgs args) private void OnListBoxSelectionChanged(object? sender, SelectionChangedEventArgs args)
{ {
if (_viewHandled) return; if (_viewHandled) return;
@ -66,7 +66,6 @@ public class MultiSelectionListBoxBehavior<T> : Behavior<ListBox>
SelectedItems = AssociatedObject.SelectedItems.Cast<T>().ToArray(); SelectedItems = AssociatedObject.SelectedItems.Cast<T>().ToArray();
} }
// Re-select items when the set of items changes
private void OnListBoxItemsChanged(object? sender, NotifyCollectionChangedEventArgs args) private void OnListBoxItemsChanged(object? sender, NotifyCollectionChangedEventArgs args)
{ {
if (_viewHandled) return; if (_viewHandled) return;
@ -82,7 +81,6 @@ public class MultiSelectionListBoxBehavior<T> : Behavior<ListBox>
((INotifyCollectionChanged) AssociatedObject.Items).CollectionChanged += OnListBoxItemsChanged; ((INotifyCollectionChanged) AssociatedObject.Items).CollectionChanged += OnListBoxItemsChanged;
} }
/// <inheritdoc />
protected override void OnDetaching() protected override void OnDetaching()
{ {
base.OnDetaching(); base.OnDetaching();

View file

@ -31,9 +31,9 @@ public static class MessageBoxViewModelExtensions
string? cancelButtonText) string? cancelButtonText)
{ {
var viewModel = factory.CreateMessageBoxViewModel(); var viewModel = factory.CreateMessageBoxViewModel();
viewModel.Title = title; viewModel.Title = title;
viewModel.Message = message; viewModel.Message = message;
viewModel.IsOkButtonVisible = !string.IsNullOrWhiteSpace(okButtonText); viewModel.IsOkButtonVisible = !string.IsNullOrWhiteSpace(okButtonText);
viewModel.OkButtonText = okButtonText; viewModel.OkButtonText = okButtonText;
viewModel.IsCancelButtonVisible = !string.IsNullOrWhiteSpace(cancelButtonText); viewModel.IsCancelButtonVisible = !string.IsNullOrWhiteSpace(cancelButtonText);