@page "/scheduled" @attribute [Authorize] @inherits LocalizableComponentBase @Localizer["Scheduled posts"] @* The current persona's posts waiting for their time (/api/v1/scheduled_statuses): moved to another time, or dropped so they are never published. The composer schedules them. *@

@Localizer["Scheduled posts"]

@if (IsLoading) {

@Localizer["loading"]

} else if (scheduled.Count == 0) {

@Localizer["Nothing is waiting to be published."]

}
@foreach (var item in scheduled) {
@item.ScheduledAt.ToLocalTime().ToString(SUtility.dateTimeFormatExt) @VisibilityName(item.Params.Visibility) @if (item.MediaAttachments.Count > 0) { @item.MediaAttachments.Count }
@if (item.Params.SpoilerText is { Length: > 0 } warning) {

@warning

}

@item.Params.Text

@Localizer["Move"] @Localizer["Never publish it"]
}
@code { [Inject] StatusService StatusService { get; set; } [Inject] ConfirmService Confirm { get; set; } List scheduled = []; readonly Dictionary moves = []; string loadedPersonaId; bool isSaving; string VisibilityName(string visibility) => visibility switch { "unlisted" => Localizer["Unlisted"], "private" => Localizer["Followers only"], "direct" => Localizer["Direct"], _ => Localizer["Public"] }; // The persona changed (NavMenu's switcher): its scheduled posts are another persona's. protected override async Task OnParametersSetAsync() { if (CascadingState.PersonaId is null) { IsLoading = false; return; } if (CascadingState.PersonaId == loadedPersonaId) return; loadedPersonaId = CascadingState.PersonaId; if (CascadingState.IsOffline) { WhenOnline(LoadData); StartOnlinePolling(); IsLoading = false; return; } await LoadData(); } async Task LoadData() { IsLoading = true; moves.Clear(); scheduled = await StatusService.Scheduled(); IsLoading = false; } async Task Move(ScheduledStatus item) { if (!DateTime.TryParse(moves[item.Id], System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AssumeLocal, out var local)) return; isSaving = true; var result = await StatusService.Reschedule(item.Id, local.ToUniversalTime()); isSaving = false; if (result.IsInvalid) { Toast.AddResponseError(result); return; } var moved = (ScheduledStatus)result.Data; moves.Remove(item.Id); item.ScheduledAt = moved.ScheduledAt; scheduled = [.. scheduled.OrderBy(s => s.ScheduledAt)]; Toast.AddResponseSuccess(Localizer["Scheduled for {0}.", moved.ScheduledAt.ToLocalTime().ToString(SUtility.dateTimeFormatExt)]); } async Task Drop(ScheduledStatus item) { if (!await Confirm.Ask(Localizer["Never publish this post?"], null, Localizer["Never publish it"], true)) return; isSaving = true; var result = await StatusService.Unschedule(item.Id); isSaving = false; if (result.IsInvalid) { Toast.AddResponseError(result); return; } scheduled.Remove(item); Toast.AddResponseSuccess(Localizer["It will not be published."]); } }