@page "/about" @inherits LocalizableComponentBase @Localizer["About {0}", instance?.Title ?? "PrivaPub"] @* What this server says of itself, to anyone, signed in or not (AboutService, the Mastodon instance API without credentials): its name, short description and thumbnail, its long description, who answers for it, its rules, its privacy policy and terms of service, and the domain blocks its administrator published (an obfuscated one partly starred, as the server gives it). The documents are the server's sanitized HTML. *@
@if (IsLoading) {

@Localizer["loading"]

} else if (instance is null) {

@Localizer["The server's description could not be read."]

@Localizer["Retry"]
} else {
@if (instance.Thumbnail.Url is { Length: > 0 } thumbnail) { @* decorative: the server's name follows *@ }

@instance.Title

@if (instance.Domain is { Length: > 0 } domain) {

@domain

} @if (instance.Description is { Length: > 0 } summary) {

@summary

}
@if (description?.Content is { Length: > 0 } extended) {
@((MarkupString)extended)
@if (description.UpdatedAt is { } describedAt) {

@Localizer["Last changed on {0}", describedAt.ToLocalTime().ToString(SUtility.dateTimeFormat)]

}
} @if (instance.Contact.Email is { Length: > 0 } || instance.Contact.Account is not null) { }

@Localizer["Rules"]

@if (instance.Rules.Count == 0) {

@Localizer["The server has no rules."]

} else {
    @foreach (var rule in instance.Rules) {
  1. @rule.Text @if (rule.Hint is { Length: > 0 } hint) {

    @hint

    }
  2. }
}
@if (privacy?.Content is { Length: > 0 } policy) {

@Localizer["Privacy policy"]

@((MarkupString)policy)
@if (privacy.UpdatedAt is { } policyAt) {

@Localizer["Last changed on {0}", policyAt.ToLocalTime().ToString(SUtility.dateTimeFormat)]

}
} @if (terms?.Content is { Length: > 0 } termsText) {

@Localizer["Terms of service"]

@if (TermsDate is { } effectiveOn) {

@(terms.Effective ? Localizer["In effect since {0}", effectiveOn] : Localizer["In effect from {0}", effectiveOn])

}
@((MarkupString)termsText)
} @if (blocks.Count > 0) {

@Localizer["Moderated servers"]

@Localizer["This server does not exchange with these, or keeps them out of its public feeds."]

    @foreach (var block in blocks) {
  • @block.Domain @switch (block.Severity) { case "suspend": @Localizer["Suspended"] break; case "silence": @Localizer["Silenced"] break; default: @Localizer["Limited"] break; }
    @if (block.Comment is { Length: > 0 } reason) {

    @reason

    }
  • }
} }
@code { [Inject] AboutService AboutService { get; set; } InstanceV2 instance; InstanceDocument description; InstanceDocument privacy; TermsOfService terms; List blocks = []; // the terms' date as the reader writes dates string TermsDate => DateTime.TryParseExact(terms?.EffectiveDate, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var on) ? on.ToString(SUtility.dateTimeFormat) : null; protected override async Task OnInitializedAsync() { if (CascadingState.IsOffline) { WhenOnline(LoadData); StartOnlinePolling(); IsLoading = false; return; } await LoadData(); IsLoading = false; } async Task LoadData() { var reading = AboutService.Instance(fresh: true); var describing = AboutService.ExtendedDescription(); var policing = AboutService.PrivacyPolicy(); var terming = AboutService.Terms(); var blocking = AboutService.DomainBlocks(); await Task.WhenAll(reading, describing, policing, terming, blocking); instance = reading.Result; description = describing.Result; privacy = policing.Result; terms = terming.Result; blocks = blocking.Result; } async Task Retry() { IsLoading = true; await LoadData(); IsLoading = false; } // signed in, the contact's profile in the app; signed out, its own page string AccountLink(Account account) => CascadingState.IsSignedIn ? $"account/{Uri.EscapeDataString(account.Id)}" : account.Url; }