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