@page "/explore" @attribute [Authorize] @inherits LocalizableComponentBase @Localizer["Explore"] @* What there is to find on PrivaPub: the hashtags, posts and links being talked about (from public posts it already holds; PrivaPub fetches nothing for them), the directory of accounts that let themselves be discovered, and the hashtags the persona follows. A hashtag opens as a tab of the feed; a link goes out to its site. *@

@Localizer["Explore"]

@Localizer["Hashtags"]
@Localizer["Popular posts"]
@Localizer["Shared links"]
@Localizer["People"]
@Localizer["Followed hashtags"]
@if (IsLoading) {

@Localizer["loading"]

} else if (tab is ExploreTab.Hashtags or ExploreTab.Followed) { @if (tags.Count == 0) {

@(tab is ExploreTab.Followed ? Localizer["This persona follows no hashtag yet."] : Localizer["Nothing is trending yet."])

}
@foreach (var item in tags) {
@(item.Following == true ? Localizer["Unfollow"] : Localizer["Follow"])
}
} else if (tab is ExploreTab.Posts) { @if (posts.Count == 0) {

@Localizer["Nothing is trending yet."]

}
@foreach (var post in posts) { }
} else if (tab is ExploreTab.Links) { @if (links.Count == 0) {

@Localizer["Nothing is trending yet."]

} } else {
@if (people.Count == 0) {

@Localizer["Empty"]

}
@foreach (var account in people) { @* alt="": the name is next to it. *@ @account.Name @("@" + account.Acct) } @if (morePeople) { @Localizer["Load more"] }
}
@code { ElementReference strip; int revealed = -1; protected override void OnAfterRender(bool firstRender) { if ((int)tab == revealed) return; revealed = (int)tab; CascadingState.Status.RevealActive(strip); } enum ExploreTab { Hashtags, Posts, Links, People, Followed } [Inject] DiscoveryService DiscoveryService { get; set; } [Inject] InstanceService InstanceService { get; set; } [Inject] ILocalStorageService LocalStorage { get; set; } ExploreTab tab = ExploreTab.Hashtags; List tags = []; List posts = []; List links = []; List people = []; DirectoryOrder order = DirectoryOrder.Active; bool localOnly; bool morePeople; bool isActing; string loadedPersonaId; static int Bar(int uses, Tag tag) => tag.History.Max(h => h.UsesCount) is > 0 and var most ? Math.Max(8, uses * 100 / most) : 8; // The persona changed (NavMenu's switcher): what it follows is 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; switch (tab) { case ExploreTab.Hashtags: tags = await DiscoveryService.TrendingTags(); break; case ExploreTab.Followed: tags = await DiscoveryService.FollowedTags(); break; case ExploreTab.Posts: posts = [.. (await DiscoveryService.TrendingStatuses()).Select(FeedPost.Of)]; await InstanceService.Resolve(posts.Select(p => p.Host).Append(InstanceService.SelfHost)); InstanceService.Locate(posts); break; case ExploreTab.Links: links = await DiscoveryService.TrendingLinks(); break; default: people = await DiscoveryService.Directory(order, localOnly, 0); morePeople = people.Count == DiscoveryService.DirectoryPage; break; } IsLoading = false; } async Task SelectTab(int index) { tab = (ExploreTab)index; await LoadData(); } async Task ChangeOrder(DirectoryOrder value) { order = value; await LoadData(); } async Task ToggleLocal(ChangeEventArgs e) { localOnly = e.Value is true; await LoadData(); } async Task LoadMorePeople() { isActing = true; var known = people.Select(a => a.Id).ToHashSet(); var page = await DiscoveryService.Directory(order, localOnly, people.Count); isActing = false; people.AddRange(page.Where(a => known.Add(a.Id))); morePeople = page.Count == DiscoveryService.DirectoryPage; } async Task ToggleFollow(Tag item) { isActing = true; var result = await DiscoveryService.FollowTag(item.Name, item.Following != true); isActing = false; if (result.IsInvalid) { Toast.AddResponseError(result); return; } item.Following = ((Tag)result.Data).Following; if (tab is ExploreTab.Followed && item.Following != true) tags.Remove(item); Toast.AddResponseSuccess(item.Following == true ? Localizer["Following #{0}: its public posts come home.", item.Name] : Localizer["No longer following #{0}.", item.Name]); } async Task OpenTag(string tagName) { var filter = await LocalStorage.GetItemAsync(nameof(FeedFilter)) ?? new(); filter.Tag = tagName; filter.TimelineType = TimelineType.Tag; await LocalStorage.SetItemAsync(nameof(FeedFilter), filter); Navigation.NavigateTo(""); } }