@page "/" @page "/home" @page "/index" @inherits LocalizableComponentBase @Localizer["Index"]
@if (IsLoading) {

@Localizer["loading"]

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

@Localizer["Empty"]

} @foreach (var message in Messages) { } @* @foreach (var message in Messages) { } @foreach (var message in Messages) { } *@
@code { [Inject] IBlazorDownloadFileService BlazorDownloadFileService { get; set; } [Inject] IStorage Storage { get; set; } [Inject] ILocalStorageService LocalStorage { get; set; } [Inject] MessagesService MessagesService { get; set; } TimelineType TimelineType { get; set; } = TimelineType.Home; TimeSortingType TimeSortingType { get; set; } = TimeSortingType.Ascending; List Messages { get; set; } = []; protected override async Task OnInitializedAsync() { var filters = await LocalStorage.GetItemAsync(nameof(ActionBarFilter)) ?? new(); TimelineType = filters.TimelineType; TimeSortingType = filters.TimeSortingType; if (CascadingState.IsOffline) { WhenOnline(LoadData); StartOnlinePolling(); IsLoading = false; return; } await LoadData(); IsLoading = false; } // The feed: the mock one in IndexedDB until the app reads PrivaPub's timeline. async Task LoadData() { Messages = await Storage.GetMessages(); } void OnTimelineChanged(TimelineType timelineType) { TimelineType = timelineType; } void OnTimeSortingChanged(TimeSortingType timeSortingType) { TimeSortingType = timeSortingType; } // Covers replies too: the form carries the RootMessageId. async Task OnMessageSubmit(MessageForm messageForm) { var result = await MessagesService.SubmitMessage(messageForm, CascadingState.User); if (result.IsInvalid) { Toast.AddResponseError(result); return; } Messages.Insert(0, result.Data as Message); } async Task OnMessageBoost(Message message) { var result = await MessagesService.BoostUnboostMessage(message); if (result.IsInvalid) { Toast.AddResponseError(result); return; } if (!message.IsBoostedByCurrentUser) { Messages.RemoveAll(m => m.MessageId == message.MessageId && m.BoostingUser?.UserId == CascadingState.User.Id); return; } // The feed shows a boost as a copy of the message carrying the booster. Messages.Insert(0, new() { BoostingUser = CascadingState.User.ToBoostingUser(), BoostsCounter = message.BoostsCounter, Content = message.Content, CreatedAt = message.CreatedAt, IsBoostedByCurrentUser = true, IsFavourite = message.IsFavourite, Medias = message.Medias, MessageId = message.MessageId, MessageType = message.MessageType, RootMessageId = message.RootMessageId, Title = message.Title, User = message.User }); } async Task OnMessageFavourite(Message message) { var result = await MessagesService.FavouriteUnfavouriteMessage(message); if (result.IsInvalid) Toast.AddResponseError(result); } async Task OnMessageDelete(Message message) { var result = await MessagesService.DeleteMessage(message); if (result.IsInvalid) { Toast.AddResponseError(result); return; } Messages.Remove(message); Toast.AddResponseSuccess(Localizer["Message deleted."]); } async Task OnMessageMediaDownload(Media media) { await BlazorDownloadFileService.DownloadFileAsync(media.FileName, media.Blob, media.ContentType); } async Task OnUserBlock(MessageUser messageUser) { var result = await MessagesService.BlockUserFromMessage(messageUser); if (result.IsInvalid) { Toast.AddResponseError(result); return; } Toast.AddResponseSuccess(Localizer["{0} blocked.", messageUser.DisplayName]); } async Task OnUserDirectMessage(Message message) { var result = await MessagesService.ReplyMessage(message, MessageType.Direct); if (result.IsInvalid) Toast.AddResponseError(result); } async Task OnUserSilence(MessageUser messageUser) { var result = await MessagesService.SilenceUserFromMessage(messageUser); if (result.IsInvalid) { Toast.AddResponseError(result); return; } Toast.AddResponseSuccess(Localizer["{0} muted.", messageUser.DisplayName]); } }