[sln] Code cleanup
This commit is contained in:
parent
28b57e35a3
commit
afe62b0aab
95 changed files with 580 additions and 523 deletions
|
@ -16,7 +16,11 @@ namespace Iceshrimp.Backend.Controllers.Federation;
|
|||
[Route("/nodeinfo")]
|
||||
[EnableCors("well-known")]
|
||||
[Produces(MediaTypeNames.Application.Json)]
|
||||
public class NodeInfoController(IOptions<Config.InstanceSection> instanceConfig, IOptions<Config.StorageSection> storageConfig, DatabaseContext db) : ControllerBase
|
||||
public class NodeInfoController(
|
||||
IOptions<Config.InstanceSection> instanceConfig,
|
||||
IOptions<Config.StorageSection> storageConfig,
|
||||
DatabaseContext db
|
||||
) : ControllerBase
|
||||
{
|
||||
[HttpGet("2.1")]
|
||||
[HttpGet("2.0")]
|
||||
|
@ -92,30 +96,30 @@ public class NodeInfoController(IOptions<Config.InstanceSection> instanceConfig,
|
|||
EnableGithubIntegration = false,
|
||||
EnableDiscordIntegration = false,
|
||||
EnableEmail = false,
|
||||
PublicTimelineVisibility = new() {
|
||||
PublicTimelineVisibility = new NodeInfoResponse.PleromaPublicTimelineVisibility
|
||||
{
|
||||
Bubble = false,
|
||||
Federated = false,
|
||||
Local = false,
|
||||
Local = false
|
||||
},
|
||||
UploadLimits = new() {
|
||||
// @formatter:off
|
||||
UploadLimits = new NodeInfoResponse.PleromaUploadLimits
|
||||
{
|
||||
General = maxUploadSize,
|
||||
Avatar = maxUploadSize,
|
||||
Background = maxUploadSize,
|
||||
Banner = maxUploadSize,
|
||||
Banner = maxUploadSize
|
||||
},
|
||||
Suggestions = new() {
|
||||
Enabled = false
|
||||
},
|
||||
Federation = new() {
|
||||
Enabled = true
|
||||
}
|
||||
// @formatter:on
|
||||
Suggestions = new NodeInfoResponse.PleromaSuggestions { Enabled = false },
|
||||
Federation = new NodeInfoResponse.PleromaFederation { Enabled = true }
|
||||
},
|
||||
OpenRegistrations = false
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("2.0.json")]
|
||||
public IActionResult GetNodeInfoAkkoFE()
|
||||
public IActionResult GetNodeInfoAkkoma()
|
||||
{
|
||||
return Redirect("/nodeinfo/2.0");
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ public class ConversationsController(
|
|||
var user = HttpContext.GetUserOrFail();
|
||||
var conversation = await db.Conversations(user)
|
||||
.IncludeCommonProperties()
|
||||
.Where(p => (p.ThreadIdOrId) == id)
|
||||
.Where(p => p.ThreadIdOrId == id)
|
||||
.Select(p => new Conversation
|
||||
{
|
||||
Id = p.ThreadIdOrId,
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Net.Mime;
|
|||
using Iceshrimp.Backend.Controllers.Mastodon.Attributes;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Schemas;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Controllers.Pleroma.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Controllers.Shared.Attributes;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
|
@ -33,15 +34,14 @@ public class InstanceController(DatabaseContext db, MetaService meta) : Controll
|
|||
|
||||
var (instanceName, instanceDescription, adminContact) =
|
||||
await meta.GetMany(MetaEntity.InstanceName, MetaEntity.InstanceDescription, MetaEntity.AdminContactEmail);
|
||||
var vapidKey = await meta.Get(MetaEntity.VapidPublicKey); // can't merge with above call since they're all nullable and this is not.
|
||||
|
||||
// can't merge with above call since they're all nullable and this is not.
|
||||
var vapidKey = await meta.Get(MetaEntity.VapidPublicKey);
|
||||
|
||||
return new InstanceInfoV1Response(config.Value, instanceName, instanceDescription, adminContact)
|
||||
{
|
||||
Stats = new InstanceStats(userCount, noteCount, instanceCount),
|
||||
Pleroma = new() {
|
||||
VapidPublicKey = vapidKey,
|
||||
Metadata = new(),
|
||||
}
|
||||
Pleroma = new PleromaInstanceExtensions { VapidPublicKey = vapidKey, Metadata = new InstanceMetadata() }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class NotificationController(DatabaseContext db, NotificationRenderer not
|
|||
.FirstOrDefaultAsync() ??
|
||||
throw GracefulException.RecordNotFound();
|
||||
|
||||
var res = await notificationRenderer.RenderAsync(notification.EnforceRenoteReplyVisibility(p => p.Note), user, isPleroma);
|
||||
return res;
|
||||
return await notificationRenderer.RenderAsync(notification.EnforceRenoteReplyVisibility(p => p.Note),
|
||||
user, isPleroma);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Controllers.Pleroma.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
|
@ -162,10 +163,7 @@ public class NoteRenderer(
|
|||
Poll = poll,
|
||||
Reactions = reactions,
|
||||
Filtered = filterResult,
|
||||
Pleroma = new() {
|
||||
Reactions = reactions,
|
||||
ConversationId = note.ThreadIdOrId
|
||||
}
|
||||
Pleroma = new PleromaStatusExtensions { Reactions = reactions, ConversationId = note.ThreadIdOrId }
|
||||
};
|
||||
|
||||
return res;
|
||||
|
@ -321,7 +319,11 @@ public class NoteRenderer(
|
|||
db.NoteReactions.Any(i => i.NoteId == p.First().NoteId &&
|
||||
i.Reaction == p.First().Reaction &&
|
||||
i.User == user),
|
||||
AccountIds = db.NoteReactions.Where(i => i.NoteId == p.First().NoteId && p.Select(r => r.Id).Contains(i.Id)).Select(i => i.UserId).ToList()
|
||||
AccountIds = db.NoteReactions
|
||||
.Where(i => i.NoteId == p.First().NoteId &&
|
||||
p.Select(r => r.Id).Contains(i.Id))
|
||||
.Select(i => i.UserId)
|
||||
.ToList()
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Controllers.Pleroma.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
|
@ -29,7 +30,8 @@ public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer,
|
|||
await userRenderer.RenderAsync(dbNotifier);
|
||||
|
||||
string? emojiUrl = null;
|
||||
if (notification.Reaction != null) {
|
||||
if (notification.Reaction != null)
|
||||
{
|
||||
// explicitly check to skip another database call if url is actually null
|
||||
if (emojiUrls != null)
|
||||
{
|
||||
|
@ -38,7 +40,10 @@ public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer,
|
|||
else if (EmojiService.IsCustomEmoji(notification.Reaction))
|
||||
{
|
||||
var parts = notification.Reaction.Trim(':').Split('@');
|
||||
emojiUrl = await db.Emojis.Where(e => e.Name == parts[0] && e.Host == (parts.Length > 1 ? parts[1] : null)).Select(e => e.PublicUrl).FirstOrDefaultAsync();
|
||||
emojiUrl = await db.Emojis
|
||||
.Where(e => e.Name == parts[0] && e.Host == (parts.Length > 1 ? parts[1] : null))
|
||||
.Select(e => e.PublicUrl)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,9 +56,7 @@ public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer,
|
|||
CreatedAt = notification.CreatedAt.ToStringIso8601Like(),
|
||||
Emoji = notification.Reaction,
|
||||
EmojiUrl = emojiUrl,
|
||||
Pleroma = new() {
|
||||
IsSeen = notification.IsRead
|
||||
}
|
||||
Pleroma = new PleromaNotificationExtensions { IsSeen = notification.IsRead }
|
||||
};
|
||||
|
||||
return res;
|
||||
|
@ -85,20 +88,28 @@ public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer,
|
|||
.DistinctBy(p => p.Id),
|
||||
user, Filter.FilterContext.Notifications, accounts);
|
||||
|
||||
var parts = notifications.Where(p => p.Reaction != null && EmojiService.IsCustomEmoji(p.Reaction)).Select(p => {
|
||||
var parts = notificationList.Where(p => p.Reaction != null && EmojiService.IsCustomEmoji(p.Reaction))
|
||||
.Select(p =>
|
||||
{
|
||||
var parts = p.Reaction!.Trim(':').Split('@');
|
||||
return new { Name = parts[0], Host = parts.Length > 1 ? parts[1] : null };
|
||||
});
|
||||
|
||||
// https://github.com/dotnet/efcore/issues/31492
|
||||
//TODO: is there a better way of expressing this using LINQ?
|
||||
IQueryable<Emoji> urlQ = db.Emojis;
|
||||
foreach (var part in parts)
|
||||
urlQ = urlQ.Concat(db.Emojis.Where(e => e.Name == part.Name && e.Host == part.Host));
|
||||
var emojiUrls = (await urlQ
|
||||
.Select(e => new { Name = $":{e.Name}{(e.Host != null ? "@" + e.Host : "")}:", Url = e.PublicUrl })
|
||||
.ToArrayAsync())
|
||||
.DistinctBy(e => e.Name)
|
||||
.ToDictionary(e => e.Name, e => e.Url);
|
||||
|
||||
//TODO: can we somehow optimize this to do the dedupe database side?
|
||||
var emojiUrls = await urlQ.Select(e => new
|
||||
{
|
||||
Name = $":{e.Name}{(e.Host != null ? "@" + e.Host : "")}:",
|
||||
Url = e.PublicUrl
|
||||
})
|
||||
.ToArrayAsync()
|
||||
.ContinueWithResult(res => res.DistinctBy(e => e.Name)
|
||||
.ToDictionary(e => e.Name, e => e.Url));
|
||||
|
||||
return await notificationList
|
||||
.Select(p => RenderAsync(p, user, isPleroma, accounts, notes, emojiUrls))
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using Iceshrimp.Backend.Controllers.Pleroma.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using J = System.Text.Json.Serialization.JsonPropertyNameAttribute;
|
||||
using static Iceshrimp.Backend.Core.Database.Tables.Notification;
|
||||
using Iceshrimp.Backend.Controllers.Pleroma.Schemas.Entities;
|
||||
|
||||
namespace Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
|
||||
|
||||
|
|
|
@ -45,9 +45,7 @@ public abstract class StatusSchemas
|
|||
|
||||
[B(Name = "poll")] [J("poll")] public PollData? Poll { get; set; }
|
||||
|
||||
[B(Name = "preview")]
|
||||
[J("preview")]
|
||||
public bool Preview { get; set; } = false;
|
||||
[B(Name = "preview")] [J("preview")] public bool Preview { get; set; } = false;
|
||||
|
||||
public class PollData
|
||||
{
|
||||
|
|
|
@ -21,11 +21,13 @@ public class EmojiController(DatabaseContext db) : ControllerBase
|
|||
[ProducesResults(HttpStatusCode.OK)]
|
||||
public async Task<Dictionary<string, PleromaEmojiEntity>> GetCustomEmojis()
|
||||
{
|
||||
var emoji = await db.Emojis.Where(p => p.Host == null)
|
||||
.Select(p => KeyValuePair.Create(p.Name, new PleromaEmojiEntity
|
||||
var emoji = await db.Emojis
|
||||
.Where(p => p.Host == null)
|
||||
.Select(p => KeyValuePair.Create(p.Name,
|
||||
new PleromaEmojiEntity
|
||||
{
|
||||
ImageUrl = p.PublicUrl,
|
||||
Tags = new string[] { p.Category == null ? "" : p.Category }
|
||||
Tags = new[] { p.Category ?? "" }
|
||||
}))
|
||||
.ToArrayAsync();
|
||||
|
||||
|
|
|
@ -4,10 +4,8 @@ using Iceshrimp.Backend.Controllers.Mastodon.Attributes;
|
|||
using Iceshrimp.Backend.Controllers.Mastodon.Renderers;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Controllers.Pleroma.Schemas;
|
||||
using Iceshrimp.Backend.Controllers.Pleroma.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Controllers.Shared.Attributes;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
|
@ -27,17 +25,17 @@ public class NotificationController(DatabaseContext db, NotificationRenderer not
|
|||
[HttpPost("/api/v1/pleroma/notifications/read")]
|
||||
[Authorize("read:notifications")]
|
||||
[ProducesResults(HttpStatusCode.OK)]
|
||||
public async Task<List<NotificationEntity>> MarkNotificationsAsRead([FromHybrid] PleromaNotificationSchemas.ReadNotificationsRequest request)
|
||||
public async Task<List<NotificationEntity>> MarkNotificationsAsRead(
|
||||
[FromHybrid] PleromaNotificationSchemas.ReadNotificationsRequest request
|
||||
)
|
||||
{
|
||||
var user = HttpContext.GetUserOrFail();
|
||||
|
||||
if (request.Id != null && request.MaxId != null)
|
||||
if (request is { Id: not null, MaxId: not null })
|
||||
throw GracefulException.BadRequest("id and max_id are mutually exclusive.");
|
||||
|
||||
var q = db.Notifications
|
||||
.IncludeCommonProperties()
|
||||
.Include(p => p.Notifier)
|
||||
.Include(p => p.Note)
|
||||
.Where(p => p.Notifiee == user)
|
||||
.Where(p => p.Notifier != null)
|
||||
.Where(p => !p.IsRead)
|
||||
|
|
|
@ -11,7 +11,22 @@ public class PleromaInstanceExtensions
|
|||
public class InstanceMetadata
|
||||
{
|
||||
[J("post_formats")] public string[] PostFormats => ["text/plain", "text/x.misskeymarkdown"];
|
||||
[J("features")] public string[] Features => ["pleroma_api", "akkoma_api", "mastodon_api", "mastodon_api_streaming", "polls", "quote_posting", "editing", "pleroma_emoji_reactions", "exposable_reactions", "custom_emoji_reactions"];
|
||||
|
||||
[J("features")]
|
||||
public string[] Features =>
|
||||
[
|
||||
"pleroma_api",
|
||||
"akkoma_api",
|
||||
"mastodon_api",
|
||||
"mastodon_api_streaming",
|
||||
"polls",
|
||||
"quote_posting",
|
||||
"editing",
|
||||
"pleroma_emoji_reactions",
|
||||
"exposable_reactions",
|
||||
"custom_emoji_reactions"
|
||||
];
|
||||
|
||||
[J("fields_limits")] public FieldsLimits FieldsLimits => new();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,12 @@ using J = System.Text.Json.Serialization.JsonPropertyNameAttribute;
|
|||
|
||||
namespace Iceshrimp.Backend.Controllers.Pleroma.Schemas;
|
||||
|
||||
public class FrontendConfigurationsResponse()
|
||||
public class FrontendConfigurationsResponse
|
||||
{
|
||||
[J("pleroma_fe")] public PleromaFeConfiguration PleromaFe => new();
|
||||
}
|
||||
|
||||
|
||||
public class PleromaFeConfiguration()
|
||||
public class PleromaFeConfiguration
|
||||
{
|
||||
[J("loginMethod")] public string LoginMethod => "token";
|
||||
[J("useStreamingApi")] public bool UseStreamingApi => true;
|
||||
|
|
|
@ -2,12 +2,10 @@ using System.Net;
|
|||
using System.Net.Mime;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Attributes;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Renderers;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Schemas;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
|
||||
using Iceshrimp.Backend.Controllers.Shared.Attributes;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using Iceshrimp.Backend.Core.Services;
|
||||
|
|
|
@ -31,7 +31,6 @@ public class IdenticonController : ControllerBase
|
|||
var gradient = new LinearGradientBrush(new Point(0, 0), new Point(Size, Size), GradientRepetitionMode.None,
|
||||
new ColorStop(0, color.start), new ColorStop(1, color.end));
|
||||
|
||||
|
||||
image.Mutate(p => p.Fill(gradient));
|
||||
|
||||
var paint = new SolidBrush(Color.White);
|
||||
|
|
|
@ -12,7 +12,7 @@ public static class FilterRenderer
|
|||
Expiry = filter.Expiry,
|
||||
Keywords = filter.Keywords,
|
||||
Action = (FilterResponse.FilterAction)filter.Action,
|
||||
Contexts = filter.Contexts.Cast<FilterResponse.FilterContext>().ToList(),
|
||||
Contexts = filter.Contexts.Cast<FilterResponse.FilterContext>().ToList()
|
||||
};
|
||||
|
||||
public static IEnumerable<FilterResponse> RenderMany(IEnumerable<Filter> filters) => filters.Select(RenderOne);
|
||||
|
|
|
@ -30,7 +30,7 @@ public class SettingsController(DatabaseContext db) : ControllerBase
|
|||
AlwaysMarkSensitive = settings.AlwaysMarkSensitive,
|
||||
AutoAcceptFollowed = settings.AutoAcceptFollowed,
|
||||
DefaultNoteVisibility = (NoteVisibility)settings.DefaultNoteVisibility,
|
||||
DefaultRenoteVisibility = (NoteVisibility)settings.DefaultNoteVisibility,
|
||||
DefaultRenoteVisibility = (NoteVisibility)settings.DefaultNoteVisibility
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -537,7 +537,7 @@ public static class QueryableExtensions
|
|||
)
|
||||
{
|
||||
if (request.ExcludeReplies)
|
||||
query = query.Where(p => p.Reply == null && p.ReplyUri == null || p.ReplyUserId == p.UserId);
|
||||
query = query.Where(p => (p.Reply == null && p.ReplyUri == null) || p.ReplyUserId == p.UserId);
|
||||
if (request.ExcludeRenotes)
|
||||
query = query.Where(p => p.Renote == null && p.RenoteUri == null);
|
||||
if (request.Tagged != null)
|
||||
|
|
|
@ -112,8 +112,24 @@ public class NodeInfoResponse
|
|||
[J("enableEmail")] public bool? EnableEmail { get; set; }
|
||||
|
||||
[J("post_formats")] public string[] PostFormats => ["text/plain", "text/x.misskeymarkdown"];
|
||||
[J("features")] public string[] Features => ["pleroma_api", "akkoma_api", "mastodon_api", "mastodon_api_streaming", "polls", "quote_posting", "editing", "pleroma_emoji_reactions", "exposable_reactions", "custom_emoji_reactions"];
|
||||
|
||||
[J("features")]
|
||||
public string[] Features =>
|
||||
[
|
||||
"pleroma_api",
|
||||
"akkoma_api",
|
||||
"mastodon_api",
|
||||
"mastodon_api_streaming",
|
||||
"polls",
|
||||
"quote_posting",
|
||||
"editing",
|
||||
"pleroma_emoji_reactions",
|
||||
"exposable_reactions",
|
||||
"custom_emoji_reactions"
|
||||
];
|
||||
|
||||
[J("localBubbleInstances")] public string[] LocalBubbleInstances { get; set; } = [];
|
||||
|
||||
// TODO: list of ap object ids i believe?
|
||||
[J("staffAccounts")] public string[] StaffAccounts { get; set; } = [];
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ public static class BlurhashHelper
|
|||
var dc = factors[0];
|
||||
var acCount = componentsX * componentsY - 1;
|
||||
|
||||
var sizeFlag = (componentsX - 1) + (componentsY - 1) * 9;
|
||||
var sizeFlag = componentsX - 1 + (componentsY - 1) * 9;
|
||||
sizeFlag.EncodeBase83(resultBuffer[..1]);
|
||||
|
||||
float maximumValue;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
|
@ -39,16 +40,18 @@ public class EmojiImportService(
|
|||
|
||||
try
|
||||
{
|
||||
var meta = archive.GetEntry("meta.json")
|
||||
?? throw GracefulException.BadRequest("Invalid emoji zip. Only Misskey-style emoji zips are supported.");
|
||||
var meta = archive.GetEntry("meta.json") ??
|
||||
throw GracefulException
|
||||
.BadRequest("Invalid emoji zip. Only Misskey-style emoji zips are supported.");
|
||||
|
||||
var metaJson = await JsonSerializer.DeserializeAsync<EmojiZipMeta>(meta.Open(), SerializerOptions)
|
||||
?? throw GracefulException.BadRequest("Invalid emoji zip metadata");
|
||||
var metaJson = await JsonSerializer.DeserializeAsync<EmojiZipMeta>(meta.Open(), SerializerOptions) ??
|
||||
throw GracefulException.BadRequest("Invalid emoji zip metadata");
|
||||
|
||||
if (metaJson.MetaVersion < 1 || metaJson.MetaVersion > 2)
|
||||
throw GracefulException.BadRequest("Unrecognized metaVersion {version}, expected 1 or 2", metaJson.MetaVersion.ToString());
|
||||
throw GracefulException.BadRequest("Unrecognized metaVersion {version}, expected 1 or 2",
|
||||
metaJson.MetaVersion.ToString());
|
||||
|
||||
return new(metaJson, archive);
|
||||
return new EmojiZip(metaJson, archive);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -97,7 +100,7 @@ public class EmojiImportService(
|
|||
|
||||
logger.LogDebug("Imported emoji {emoji}", name);
|
||||
}
|
||||
catch (GracefulException e) when (e.StatusCode == System.Net.HttpStatusCode.Conflict)
|
||||
catch (GracefulException e) when (e.StatusCode == HttpStatusCode.Conflict)
|
||||
{
|
||||
logger.LogDebug("Skipping {emoji} as it already exists.", name);
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ public class ImageProcessor
|
|||
_logger.LogWarning("No image processor supports the format {format}, skipping", p.Format.MimeType);
|
||||
return null;
|
||||
}
|
||||
|
||||
return async () =>
|
||||
{
|
||||
if (_concurrency is 0)
|
||||
|
|
|
@ -11,7 +11,8 @@ using Microsoft.EntityFrameworkCore;
|
|||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// This is needed because static fields in generic classes aren't shared between instances with different generic type arguments
|
||||
/// This is needed because static fields in generic classes aren't shared between instances with different generic type
|
||||
/// arguments
|
||||
/// </summary>
|
||||
file static class PluginStoreHelpers
|
||||
{
|
||||
|
|
|
@ -91,7 +91,7 @@ public class AuthorizeModel(DatabaseContext db) : PageModel
|
|||
RedirectUri = RedirectUri,
|
||||
AutoDetectQuotes = autoDetectQuotes,
|
||||
SupportsHtmlFormatting = supportsHtmlFormatting,
|
||||
IsPleroma = isPleroma,
|
||||
IsPleroma = isPleroma
|
||||
};
|
||||
|
||||
await db.AddAsync(token);
|
||||
|
|
|
@ -13,7 +13,7 @@ public class QueueJobModel(DatabaseContext db) : PageModel
|
|||
{
|
||||
["inbox"] = "body",
|
||||
["deliver"] = "payload",
|
||||
["pre-deliver"] = "serializedActivity",
|
||||
["pre-deliver"] = "serializedActivity"
|
||||
};
|
||||
|
||||
public Job Job = null!;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@using Iceshrimp.Frontend.Components
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
<ErrorBoundary @ref=ErrorBoundary>
|
||||
<ErrorBoundary @ref="ErrorBoundary">
|
||||
<ChildContent>
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
|
||||
@if (Attachment.ContentType.StartsWith("image"))
|
||||
{
|
||||
<div class="wrapper" @onclick="Open" @onclick:stopPropagation="true">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div @onclick="Close" @onclick:stopPropagation="true" class="backdrop @(Darken ? "darken" : "")"></div>
|
||||
|
||||
@code {
|
||||
[Parameter][EditorRequired] public required EventCallback OnClose { get; set; }
|
||||
[Parameter] [EditorRequired] public required EventCallback OnClose { get; set; }
|
||||
[Parameter] public bool Darken { get; set; }
|
||||
|
||||
private void Close()
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<Icon Name="Icons.X"/>
|
||||
</button>
|
||||
<Dropdown TBind="NoteVisibility" Elements="@DropDownCreate()" @bind-Value="NoteDraft.Visibility"/>
|
||||
<StateButton OnClick="SendNote" @ref=SendButton ExtraClasses="post-btn">
|
||||
<StateButton OnClick="SendNote" @ref="SendButton" ExtraClasses="post-btn">
|
||||
<Initial>
|
||||
@Loc["ComposePost"]<Icon Name="Icons.PaperPlaneRight"/>
|
||||
</Initial>
|
||||
|
@ -84,7 +84,12 @@
|
|||
Cw = null
|
||||
};
|
||||
|
||||
private Dictionary<string, string> AvailablePlaceholders { get; set; } = new() { { "default", "What's on your mind?" }, { "reply", "Reply goes here!" }, { "quote", "Quote this post!" } };
|
||||
private Dictionary<string, string> AvailablePlaceholders { get; set; } = new()
|
||||
{
|
||||
{ "default", "What's on your mind?" },
|
||||
{ "reply", "Reply goes here!" },
|
||||
{ "quote", "Quote this post!" }
|
||||
};
|
||||
|
||||
RenderFragment DropdownIcon(NoteVisibility vis)
|
||||
{
|
||||
|
@ -117,7 +122,9 @@
|
|||
new DropdownElement<NoteVisibility>
|
||||
{
|
||||
#pragma warning disable BL0005 // Setting this outside the component is fine until this is reworked
|
||||
Icon = DropdownIcon(vis), Content = DropdownContent(vis), Selection = vis
|
||||
Icon = DropdownIcon(vis),
|
||||
Content = DropdownContent(vis),
|
||||
Selection = vis
|
||||
#pragma warning restore BL0005
|
||||
})
|
||||
.ToList();
|
||||
|
@ -212,7 +219,12 @@
|
|||
{
|
||||
ReplyOrQuote = null;
|
||||
Attachments = new List<DriveFileResponse>();
|
||||
NoteDraft = new NoteCreateRequest { Text = "", Visibility = NoteVisibility.Followers, Cw = null };
|
||||
NoteDraft = new NoteCreateRequest
|
||||
{
|
||||
Text = "",
|
||||
Visibility = NoteVisibility.Followers,
|
||||
Cw = null
|
||||
};
|
||||
TextPlaceholder = AvailablePlaceholders["default"];
|
||||
}
|
||||
|
||||
|
|
|
@ -40,8 +40,7 @@
|
|||
}
|
||||
</div>
|
||||
@Loc["Logs"]
|
||||
@Loc["These logs may contain sensitive information, please do not post them publicly.\n" +
|
||||
"Providing them to developers upon request may help with debugging."]
|
||||
@Loc["These logs may contain sensitive information, please do not post them publicly.\n" + "Providing them to developers upon request may help with debugging."]
|
||||
<div class="log-block">
|
||||
<pre><code>
|
||||
@foreach (var line in _rawLog)
|
||||
|
@ -70,14 +69,12 @@
|
|||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_rawLog = LogService.GetLogs();
|
||||
_module = (IJSInProcessObjectReference) await Js.InvokeAsync<IJSObjectReference>("import", "./Components/ErrorUi.razor.js");
|
||||
_module = (IJSInProcessObjectReference)await Js.InvokeAsync<IJSObjectReference>("import", "./Components/ErrorUi.razor.js");
|
||||
}
|
||||
|
||||
|
||||
private void DownloadLogs()
|
||||
{
|
||||
var logBytes = LogService.GetLogs().SelectMany(p => Encoding.UTF8.GetBytes(p)).ToArray();
|
||||
_module.InvokeVoid("DownloadFile", "log.txt", "text/plain", logBytes);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.Extensions.Localization
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
@inject ApiService Api;
|
||||
<span class="follow-button">
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.Extensions.Localization
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
@inject ApiService Api;
|
||||
@inject NavigationManager NavigationManager;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<EmojiPicker></EmojiPicker>
|
||||
@code {
|
||||
|
||||
@code {
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
@if (_display)
|
||||
{
|
||||
<div class="menu">
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
|
||||
<div @onclick="OnClick" class="menu-element">
|
||||
@if (Icon != null)
|
||||
{
|
||||
|
@ -7,6 +6,7 @@
|
|||
}
|
||||
@Text
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public IconName? Icon { get; set; }
|
||||
[Parameter] [EditorRequired] public required RenderFragment Text { get; set; }
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
<CascadingValue Value="this">
|
||||
|
||||
@if (NoteResponse.Renote != null)
|
||||
{
|
||||
@if (NoteResponse.Renote != null)
|
||||
{
|
||||
<div class="renote">
|
||||
<div class="renote-info">
|
||||
<span class="user">
|
||||
<Icon Name="Icons.Repeat" /> Boosted by
|
||||
<Icon Name="Icons.Repeat"/> Boosted by
|
||||
@if (NoteResponse.User.DisplayName != null)
|
||||
{
|
||||
@NoteResponse.User.DisplayName
|
||||
|
@ -22,9 +22,9 @@
|
|||
</div>
|
||||
<NoteComponent Note="NoteResponse.Renote" Quote="NoteResponse.Quote" Indented="Indented"/>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (NoteResponse.Filtered is not null && NoteResponse.Filtered.Hide == false)
|
||||
{
|
||||
<div>
|
||||
|
@ -43,11 +43,12 @@ else
|
|||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (_overrideHide || NoteResponse.Filtered == null)
|
||||
{
|
||||
<NoteComponent Note="NoteResponse" Quote="NoteResponse.Quote" Indented="Indented"/>
|
||||
}
|
||||
}
|
||||
}
|
||||
</CascadingValue>
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
@inject NavigationManager NavigationManager
|
||||
@inject ComposeService ComposeService
|
||||
@inject SessionService Session;
|
||||
<div class="note-header">
|
||||
<div class="note-header">
|
||||
<NoteUserInfo
|
||||
AvatarUrl="@Note.User.AvatarUrl"
|
||||
DisplayName="@Note.User.DisplayName"
|
||||
|
@ -16,16 +16,16 @@
|
|||
InstanceName="@Note.User.InstanceName"
|
||||
CreatedAt="DateTime.Parse(Note.CreatedAt)">
|
||||
</NoteMetadata>
|
||||
</div>
|
||||
<NoteBody NoteBase="Note" OverLength="@CheckLen()" Indented="Indented"/>
|
||||
@if (Quote != null)
|
||||
{
|
||||
</div>
|
||||
<NoteBody NoteBase="Note" OverLength="@CheckLen()" Indented="Indented"/>
|
||||
@if (Quote != null)
|
||||
{
|
||||
<div @onclick="OpenQuote" @onclick:stopPropagation="true" class="quote">
|
||||
<NoteComponent Note="Quote" AsQuote="true"></NoteComponent>
|
||||
</div>
|
||||
}
|
||||
@if (!AsQuote)
|
||||
{
|
||||
}
|
||||
@if (!AsQuote)
|
||||
{
|
||||
<NoteFooter
|
||||
Reactions="Note.Reactions"
|
||||
Likes="Note.Likes"
|
||||
|
@ -33,7 +33,7 @@
|
|||
Renotes="Note.Renotes"
|
||||
RenotePossible=
|
||||
"@(Note.Visibility == NoteVisibility.Public || Note.Visibility == NoteVisibility.Home || Session.Current?.Id == Note.User.Id)"/>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] [EditorRequired] public required NoteBase Note { get; set; }
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<button class="btn" @onclick="Reply" @onclick:stopPropagation="true">
|
||||
<Icon Name="Icons.ArrowUUpLeft" Size="1.3em"/>
|
||||
</button>
|
||||
<button class="btn @(RenotePossible ? "" : "disabled") positioned" @onclick="@(RenotePossible ? ToggleRenoteMenu : () => {})" @onclick:stopPropagation="true">
|
||||
<button class="btn @(RenotePossible ? "" : "disabled") positioned" @onclick="@(RenotePossible ? ToggleRenoteMenu : () => { })" @onclick:stopPropagation="true">
|
||||
@if (RenotePossible)
|
||||
{
|
||||
<Icon Name="Icons.Repeat" Size="1.3em"/>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
@inject NavigationManager NavigationManager
|
||||
|
||||
<div class="notification">
|
||||
@if (NotificationResponse is { User: not null, Type: "like" or "follow" or "reaction" or "followRequestReceived" or "followRequestAccepted"})
|
||||
@if (NotificationResponse is { User: not null, Type: "like" or "follow" or "reaction" or "followRequestReceived" or "followRequestAccepted" })
|
||||
{
|
||||
<img class="user-avatar" src="@NotificationResponse.User.AvatarUrl"/>
|
||||
<div class="notification-body">
|
||||
|
|
|
@ -101,7 +101,6 @@
|
|||
Note.Descendants = res;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OpenNote()
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@using System.Diagnostics.CodeAnalysis
|
||||
@* ReSharper disable once RedundantUsingDirective *@
|
||||
@using Iceshrimp.Frontend.Components.Note
|
||||
@using Iceshrimp.Frontend.Core.Miscellaneous
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Microsoft.Extensions.Localization
|
||||
@* ReSharper disable once RedundantUsingDirective *@
|
||||
@using Iceshrimp.Frontend.Components.Note
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.Extensions.Localization
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
@inject ApiService Api;
|
||||
@inject NavigationManager Navigation;
|
||||
|
|
|
@ -25,5 +25,4 @@
|
|||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
|
@ -10,11 +10,11 @@
|
|||
</button>
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired] public required EventCallback OnClick { get; set; }
|
||||
[Parameter, EditorRequired] public required RenderFragment Initial { get; set; }
|
||||
[Parameter, EditorRequired] public required RenderFragment Loading { get; set; }
|
||||
[Parameter, EditorRequired] public required RenderFragment Failed { get; set; }
|
||||
[Parameter, EditorRequired] public required RenderFragment Success { get; set; }
|
||||
[Parameter] [EditorRequired] public required EventCallback OnClick { get; set; }
|
||||
[Parameter] [EditorRequired] public required RenderFragment Initial { get; set; }
|
||||
[Parameter] [EditorRequired] public required RenderFragment Loading { get; set; }
|
||||
[Parameter] [EditorRequired] public required RenderFragment Failed { get; set; }
|
||||
[Parameter] [EditorRequired] public required RenderFragment Success { get; set; }
|
||||
[Parameter] public string? ExtraClasses { get; set; }
|
||||
public StateEnum State { get; set; }
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ public partial class TimelineComponent : IAsyncDisposable
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
State.MaxId = res[0].Id;
|
||||
State.MinId = res.Last().Id;
|
||||
State.Timeline = res;
|
||||
|
@ -124,6 +125,7 @@ public partial class TimelineComponent : IAsyncDisposable
|
|||
{
|
||||
initResult = await Initialize();
|
||||
}
|
||||
|
||||
ComponentState = initResult ? Core.Miscellaneous.State.Loaded : Core.Miscellaneous.State.Empty;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
@using Iceshrimp.Frontend.Components.Note
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@inject NavigationManager Navigation
|
||||
@if (Note.Filtered is { Hide: true })
|
||||
@if (Note.Filtered is { Hide: true }) { }
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
else {
|
||||
<div class="note-container" @onclick="OpenNote" id="@Note.Id">
|
||||
<Note NoteResponse="Note"></Note>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
@code {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@inject ApiService Api;
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@inject ApiService Api;
|
||||
@inject NavigationManager NavigationManager;
|
||||
@if (UserProfile != null)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
<div @ref="@_scroller" class="scroller">
|
||||
<div @ref="@_padTopRef" class="padding top" style="height: @(State.PadTop + "px")"></div>
|
||||
@if (_loadingTop)
|
||||
|
@ -30,5 +29,4 @@
|
|||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
|
@ -277,7 +277,9 @@ public partial class VirtualScroller : IAsyncDisposable
|
|||
{
|
||||
if (firstRender)
|
||||
{
|
||||
Module = (IJSInProcessObjectReference) await Js.InvokeAsync<IJSObjectReference>("import", "./Components/VirtualScroller.razor.js");
|
||||
Module =
|
||||
(IJSInProcessObjectReference)
|
||||
await Js.InvokeAsync<IJSObjectReference>("import", "./Components/VirtualScroller.razor.js");
|
||||
await SetupObservers();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Iceshrimp.Frontend.Core.InMemoryLogger;
|
|||
internal class InMemoryLogService(IOptions<InMemoryLoggerConfiguration> configuration)
|
||||
{
|
||||
private readonly LogBuffer _buffer = new(configuration.Value.BufferSize);
|
||||
|
||||
public void Add(string logline)
|
||||
{
|
||||
_buffer.Add(logline);
|
||||
|
|
|
@ -2,9 +2,12 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Iceshrimp.Frontend.Core.InMemoryLogger;
|
||||
|
||||
internal class InMemoryLogger (IOptions<InMemoryLoggerConfiguration> config, InMemoryLogService logService) : ILogger
|
||||
internal class InMemoryLogger(IOptions<InMemoryLoggerConfiguration> config, InMemoryLogService logService) : ILogger
|
||||
{
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
|
||||
public void Log<TState>(
|
||||
LogLevel logLevel, EventId eventId, TState state, Exception? exception,
|
||||
Func<TState, Exception?, string> formatter
|
||||
)
|
||||
{
|
||||
logService.Add(formatter(state, exception));
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
namespace Iceshrimp.Frontend.Core.InMemoryLogger;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Configuration;
|
||||
|
||||
namespace Iceshrimp.Frontend.Core.InMemoryLogger;
|
||||
|
||||
internal static class InMemoryLoggerExtension
|
||||
{
|
||||
public static void AddInMemoryLogger(
|
||||
this ILoggingBuilder builder, IConfiguration configuration)
|
||||
this ILoggingBuilder builder, IConfiguration configuration
|
||||
)
|
||||
{
|
||||
builder.AddConfiguration();
|
||||
builder.Services.AddOptionsWithValidateOnStart<InMemoryLoggerConfiguration>()
|
||||
.Bind(configuration.GetSection("InMemoryLogger"));
|
||||
LoggerProviderOptions.RegisterProviderOptions<InMemoryLoggerConfiguration, InMemoryLoggerProvider>(builder.Services);
|
||||
LoggerProviderOptions
|
||||
.RegisterProviderOptions<InMemoryLoggerConfiguration, InMemoryLoggerProvider>(builder.Services);
|
||||
builder.Services.TryAddSingleton<InMemoryLogService>();
|
||||
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, InMemoryLoggerProvider>());
|
||||
}
|
||||
|
@ -28,5 +28,3 @@ internal static class InMemoryLoggerExtension
|
|||
builder.Services.Configure(configure);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ public readonly struct QueryString : IEquatable<QueryString>
|
|||
{
|
||||
ArgumentNullException.ThrowIfNull(uri);
|
||||
|
||||
string queryValue = uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped);
|
||||
var queryValue = uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped);
|
||||
if (!string.IsNullOrEmpty(queryValue))
|
||||
{
|
||||
queryValue = "?" + queryValue;
|
||||
|
@ -170,10 +170,10 @@ public readonly struct QueryString : IEquatable<QueryString>
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Concatenates <paramref name="other"/> to the current query string.
|
||||
/// Concatenates <paramref name="other" /> to the current query string.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="QueryString"/> to concatenate.</param>
|
||||
/// <returns>The concatenated <see cref="QueryString"/>.</returns>
|
||||
/// <param name="other">The <see cref="QueryString" /> to concatenate.</param>
|
||||
/// <returns>The concatenated <see cref="QueryString" />.</returns>
|
||||
public QueryString Add(QueryString other)
|
||||
{
|
||||
if (!HasValue || Value.Equals("?", StringComparison.Ordinal))
|
||||
|
@ -191,12 +191,12 @@ public readonly struct QueryString : IEquatable<QueryString>
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Concatenates a query string with <paramref name="name"/> and <paramref name="value"/>
|
||||
/// Concatenates a query string with <paramref name="name" /> and <paramref name="value" />
|
||||
/// to the current query string.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the query string to concatenate.</param>
|
||||
/// <param name="value">The value of the query string to concatenate.</param>
|
||||
/// <returns>The concatenated <see cref="QueryString"/>.</returns>
|
||||
/// <returns>The concatenated <see cref="QueryString" />.</returns>
|
||||
public QueryString Add(string name, string value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(name);
|
||||
|
@ -212,10 +212,10 @@ public readonly struct QueryString : IEquatable<QueryString>
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evalutes if the current query string is equal to <paramref name="other"/>.
|
||||
/// Evalutes if the current query string is equal to <paramref name="other" />.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="QueryString"/> to compare.</param>
|
||||
/// <returns><see langword="true"/> if the query strings are equal.</returns>
|
||||
/// <param name="other">The <see cref="QueryString" /> to compare.</param>
|
||||
/// <returns><see langword="true" /> if the query strings are equal.</returns>
|
||||
public bool Equals(QueryString other)
|
||||
{
|
||||
if (!HasValue && !other.HasValue)
|
||||
|
@ -227,7 +227,7 @@ public readonly struct QueryString : IEquatable<QueryString>
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates if the current query string is equal to an object <paramref name="obj"/>.
|
||||
/// Evaluates if the current query string is equal to an object <paramref name="obj" />.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare.</param>
|
||||
/// <returns><see langword="true" /> if the query strings are equal.</returns>
|
||||
|
@ -244,17 +244,17 @@ public readonly struct QueryString : IEquatable<QueryString>
|
|||
/// <summary>
|
||||
/// Gets a hash code for the value.
|
||||
/// </summary>
|
||||
/// <returns>The hash code as an <see cref="int"/>.</returns>
|
||||
/// <returns>The hash code as an <see cref="int" />.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (HasValue ? Value.GetHashCode() : 0);
|
||||
return HasValue ? Value.GetHashCode() : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates if one query string is equal to another.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="QueryString"/> instance.</param>
|
||||
/// <param name="right">A <see cref="QueryString"/> instance.</param>
|
||||
/// <param name="left">A <see cref="QueryString" /> instance.</param>
|
||||
/// <param name="right">A <see cref="QueryString" /> instance.</param>
|
||||
/// <returns><see langword="true" /> if the query strings are equal.</returns>
|
||||
public static bool operator ==(QueryString left, QueryString right)
|
||||
{
|
||||
|
@ -264,8 +264,8 @@ public readonly struct QueryString : IEquatable<QueryString>
|
|||
/// <summary>
|
||||
/// Evaluates if one query string is not equal to another.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="QueryString"/> instance.</param>
|
||||
/// <param name="right">A <see cref="QueryString"/> instance.</param>
|
||||
/// <param name="left">A <see cref="QueryString" /> instance.</param>
|
||||
/// <param name="right">A <see cref="QueryString" /> instance.</param>
|
||||
/// <returns><see langword="true" /> if the query strings are not equal.</returns>
|
||||
public static bool operator !=(QueryString left, QueryString right)
|
||||
{
|
||||
|
@ -273,11 +273,11 @@ public readonly struct QueryString : IEquatable<QueryString>
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Concatenates <paramref name="left"/> and <paramref name="right"/> into a single query string.
|
||||
/// Concatenates <paramref name="left" /> and <paramref name="right" /> into a single query string.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="QueryString"/> instance.</param>
|
||||
/// <param name="right">A <see cref="QueryString"/> instance.</param>
|
||||
/// <returns>The concatenated <see cref="QueryString"/>.</returns>
|
||||
/// <param name="left">A <see cref="QueryString" /> instance.</param>
|
||||
/// <param name="right">A <see cref="QueryString" /> instance.</param>
|
||||
/// <returns>The concatenated <see cref="QueryString" />.</returns>
|
||||
public static QueryString operator +(QueryString left, QueryString right)
|
||||
{
|
||||
return left.Add(right);
|
||||
|
|
|
@ -24,6 +24,4 @@ internal class EmojiService(ApiService api)
|
|||
throw new Exception("Failed to fetch emoji");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Iceshrimp.Frontend.Components;
|
||||
|
||||
namespace Iceshrimp.Frontend.Core.Services;
|
||||
|
||||
public class GlobalComponentSvc
|
||||
|
|
|
@ -9,12 +9,12 @@ internal class MessageService
|
|||
|
||||
private readonly Dictionary<(string, Type), EventHandler<NoteResponse>> _noteChangedHandlers = new();
|
||||
|
||||
|
||||
public enum Type
|
||||
{
|
||||
Updated,
|
||||
Deleted
|
||||
}
|
||||
|
||||
public NoteMessageHandler Register(string id, EventHandler<NoteResponse> func, Type type)
|
||||
{
|
||||
var tuple = (id, type);
|
||||
|
@ -52,7 +52,9 @@ internal class MessageService
|
|||
private readonly Type _type;
|
||||
private readonly MessageService _messageService;
|
||||
|
||||
public NoteMessageHandler(EventHandler<NoteResponse> handler, string id, Type type, MessageService messageService)
|
||||
public NoteMessageHandler(
|
||||
EventHandler<NoteResponse> handler, string id, Type type, MessageService messageService
|
||||
)
|
||||
{
|
||||
_handler = handler;
|
||||
_id = id;
|
||||
|
|
|
@ -14,7 +14,6 @@ public class SingleNote
|
|||
States.TryGetValue(id, out var state);
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class SingleNoteState
|
||||
|
|
|
@ -60,6 +60,7 @@ internal class TimelineState : IDisposable
|
|||
Timeline.RemoveAt(i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i == 0) MaxId = Timeline[1].Id;
|
||||
if (i == Timeline.Count - 1) MinId = Timeline[^2].Id;
|
||||
Timeline.RemoveAt(i);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="page">
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
@using Iceshrimp.Frontend.Components
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Microsoft.Extensions.Localization
|
||||
@inherits LayoutComponentBase
|
||||
@layout MainLayout
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
@inject IStringLocalizer<Localization> Loc;
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Microsoft.Extensions.Localization
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
@implements IDisposable
|
||||
@inject NavigationManager Navigation;
|
||||
|
||||
<GlobalComponents></GlobalComponents>
|
||||
<div @ref="SidebarElementRef" class="sidebar @(_open ? "open" : "")" tabindex=0>
|
||||
<div @ref="SidebarElementRef" class="sidebar @(_open ? "open" : "")" tabindex="0">
|
||||
<div class="header">
|
||||
<account-dropdown/>
|
||||
</div>
|
||||
|
@ -49,7 +49,7 @@
|
|||
</button>
|
||||
@if (_open)
|
||||
{
|
||||
<ClosingBackdrop OnClose="Close" />
|
||||
<ClosingBackdrop OnClose="Close"/>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@page "/follow-requests"
|
||||
@attribute [Authorize]
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Microsoft.Extensions.Localization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Microsoft.Extensions.Localization
|
||||
@attribute [Authorize]
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
|
||||
<SectionContent SectionName="top-bar">
|
||||
|
@ -13,7 +13,7 @@
|
|||
@Loc["Follow requests"]
|
||||
</SectionContent>
|
||||
|
||||
<FollowRequestList />
|
||||
@code {
|
||||
<FollowRequestList/>
|
||||
|
||||
@code {
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
@page "/notifications"
|
||||
@attribute [Authorize]
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Microsoft.Extensions.Localization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Microsoft.Extensions.Localization
|
||||
@attribute [Authorize]
|
||||
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
@page "/{User}"
|
||||
@attribute [Authorize]
|
||||
|
||||
@using System.Text.RegularExpressions
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Components.Note
|
||||
|
@ -8,6 +6,7 @@
|
|||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@attribute [Authorize]
|
||||
@inject ApiService Api
|
||||
|
||||
@if (_init)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@page "/search"
|
||||
@attribute [Authorize]
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Microsoft.Extensions.Localization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Microsoft.Extensions.Localization
|
||||
@attribute [Authorize]
|
||||
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
|||
@Loc["Search"]
|
||||
</SectionContent>
|
||||
|
||||
<SearchComponent />
|
||||
@code {
|
||||
<SearchComponent/>
|
||||
|
||||
@code {
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
@page "/settings/about"
|
||||
@attribute [Authorize]
|
||||
@using System.Text
|
||||
@using Iceshrimp.Frontend.Core.InMemoryLogger
|
||||
@using Iceshrimp.Frontend.Core.Services;
|
||||
@using Iceshrimp.Frontend.Localization;
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.Extensions.Localization;
|
||||
@using Microsoft.Extensions.Localization
|
||||
@attribute [Authorize]
|
||||
@layout SettingsLayout;
|
||||
@inject VersionService Version;
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
|
@ -36,8 +36,7 @@
|
|||
</div>
|
||||
<div class="logs">
|
||||
<h1>@Loc["Logs"]</h1>
|
||||
@Loc["These logs may contain sensitive information, please do not post them publicly.\n"
|
||||
+ "Providing them to developers upon request may help with debugging."]
|
||||
@Loc["These logs may contain sensitive information, please do not post them publicly.\n" + "Providing them to developers upon request may help with debugging."]
|
||||
<button class="btn" @onclick="DownloadLogs">@Loc["Download Logs"]</button>
|
||||
</div>
|
||||
|
||||
|
@ -46,7 +45,7 @@
|
|||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_module = (IJSInProcessObjectReference) await Js.InvokeAsync<IJSObjectReference>("import", "./Components/ErrorUi.razor.js");
|
||||
_module = (IJSInProcessObjectReference)await Js.InvokeAsync<IJSObjectReference>("import", "./Components/ErrorUi.razor.js");
|
||||
}
|
||||
|
||||
private void DownloadLogs()
|
||||
|
@ -54,5 +53,4 @@
|
|||
var logBytes = LogService.GetLogs().SelectMany(p => Encoding.UTF8.GetBytes(p)).ToArray();
|
||||
_module.InvokeVoid("DownloadFile", "log.txt", "text/plain", logBytes);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
@page "/settings/filters"
|
||||
@attribute [Authorize]
|
||||
@using Iceshrimp.Frontend.Core.Miscellaneous
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Core.Miscellaneous
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.Extensions.Localization
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Microsoft.Extensions.Localization
|
||||
@attribute [Authorize]
|
||||
@layout SettingsLayout
|
||||
@inject ApiService Api;
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
|
@ -177,7 +177,7 @@
|
|||
private State State { get; set; } = State.Loading;
|
||||
private string FilterName { get; set; } = "";
|
||||
private string Keyword { get; set; } = "";
|
||||
private List<String> FilterKeywords { get; } = [];
|
||||
private List<string> FilterKeywords { get; } = [];
|
||||
private DateTime? FilterExpiry { get; set; }
|
||||
private FilterResponse.FilterAction FilterAction { get; set; }
|
||||
private Menu MenuFilterAction { get; set; } = null!;
|
||||
|
@ -217,7 +217,7 @@
|
|||
|
||||
private async Task TryAddFilter()
|
||||
{
|
||||
bool valid = true;
|
||||
var valid = true;
|
||||
|
||||
if (FilterName.Length < 1)
|
||||
{
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
@page "/settings/profile"
|
||||
@attribute [Authorize]
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Core.Miscellaneous
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.Extensions.Localization
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.Extensions.Logging
|
||||
@using Microsoft.Extensions.Localization
|
||||
@attribute [Authorize]
|
||||
@layout SettingsLayout
|
||||
@inject ApiService Api;
|
||||
@inject ILogger<Profile> Logger;
|
||||
|
@ -50,10 +49,18 @@
|
|||
|
||||
<div class="section">
|
||||
<StateButton OnClick="SaveChanges" @ref="SaveButton">
|
||||
<Initial><Icon Name="Icons.FloppyDisk"/>@Loc["Save"]</Initial>
|
||||
<Loading><Icon Name="Icons.Spinner"/></Loading>
|
||||
<Failed><Icon Name="Icons.X" />@Loc["Error"]</Failed>
|
||||
<Success><Icon Name="Icons.Check"/>@Loc["Saved"]</Success>
|
||||
<Initial>
|
||||
<Icon Name="Icons.FloppyDisk"/>@Loc["Save"]
|
||||
</Initial>
|
||||
<Loading>
|
||||
<Icon Name="Icons.Spinner"/>
|
||||
</Loading>
|
||||
<Failed>
|
||||
<Icon Name="Icons.X"/>@Loc["Error"]
|
||||
</Failed>
|
||||
<Success>
|
||||
<Icon Name="Icons.Check"/>@Loc["Saved"]
|
||||
</Success>
|
||||
</StateButton>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@page "/Settings"
|
||||
@attribute [Authorize]
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Microsoft.Extensions.Localization
|
||||
@attribute [Authorize]
|
||||
@* @inject NavigationManager Nav; *@
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
|
||||
|
|
|
@ -1,16 +1,5 @@
|
|||
@page "/notes/{NoteId}"
|
||||
@attribute [Authorize]
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Components.Note
|
||||
@using Iceshrimp.Frontend.Core.Miscellaneous
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Frontend.Core.Services.StateServicePatterns
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.Extensions.Localization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@inject ApiService ApiService
|
||||
@inject IJSRuntime Js
|
||||
@inject MessageService MessageService
|
||||
|
@ -19,6 +8,17 @@
|
|||
@inject IStringLocalizer<Localization> Loc
|
||||
@inject ILogger<SingleNote> Logger;
|
||||
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Components.Note
|
||||
@using Iceshrimp.Frontend.Core.Miscellaneous
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Frontend.Core.Services.StateServicePatterns
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Microsoft.Extensions.Localization
|
||||
@implements IDisposable
|
||||
|
||||
@if (_componentState == LoadState.Init)
|
||||
|
@ -114,11 +114,13 @@
|
|||
_componentState = LoadState.Error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (RootNote == null)
|
||||
{
|
||||
_componentState = LoadState.Error;
|
||||
return;
|
||||
}
|
||||
|
||||
_componentState = LoadState.Init;
|
||||
|
||||
StateHasChanged();
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@page "/"
|
||||
@attribute [Authorize]
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Iceshrimp.Assets.PhosphorIcons
|
||||
@using Iceshrimp.Frontend.Components
|
||||
@using Iceshrimp.Frontend.Localization
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Sections
|
||||
@using Microsoft.Extensions.Localization
|
||||
@attribute [Authorize]
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
|
||||
<SectionContent SectionName="top-bar">
|
||||
|
|
|
@ -4,9 +4,7 @@ open System
|
|||
open FParsec
|
||||
|
||||
module SearchQueryFilters =
|
||||
type Filter() =
|
||||
class
|
||||
end
|
||||
type Filter() = class end
|
||||
|
||||
type WordFilter(neg: bool, value: string) =
|
||||
inherit Filter()
|
||||
|
|
|
@ -268,7 +268,7 @@ public class MfmTests
|
|||
List<MfmNode> expected =
|
||||
[
|
||||
new MfmTextNode("this is plain text > this is not a quote >this is also not a quote\n"),
|
||||
new MfmQuoteNode(ListModule.OfSeq<MfmInlineNode>([new MfmTextNode("this is a quote\nthis is part of the same quote\nthis too"),]), false, false),
|
||||
new MfmQuoteNode(ListModule.OfSeq<MfmInlineNode>([new MfmTextNode("this is a quote\nthis is part of the same quote\nthis too")]), false, false),
|
||||
new MfmTextNode("this is some plain text inbetween\n"),
|
||||
new MfmQuoteNode(ListModule.OfSeq<MfmInlineNode>([new MfmTextNode("this is a second quote\nthis is part of the second quote")]), true, false),
|
||||
new MfmQuoteNode(ListModule.OfSeq<MfmInlineNode>([new MfmTextNode("this is a third quote")]), false, false),
|
||||
|
|
Loading…
Add table
Reference in a new issue