Skip to content
This repository has been archived by the owner on Dec 20, 2023. It is now read-only.

支持关注列表分组 #1104

Merged
merged 1 commit into from
Apr 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/App/App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,9 @@
<Compile Include="Controls\Common\VerticalRepeaterView\VerticalRepeaterView.cs" />
<Compile Include="Controls\VisualExtensions.cs" />
<Compile Include="Pages\AppPage.cs" />
<Compile Include="Pages\Overlay\MyFollowsPage.xaml.cs">
<DependentUpon>MyFollowsPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\Overlay\FansPage.xaml.cs">
<DependentUpon>FansPage.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -998,6 +1001,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\Overlay\MyFollowsPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\Overlay\FansPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down
3 changes: 3 additions & 0 deletions src/App/Controls/App/RootNavigationView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ private void CheckOverlayContentNavigation(object param)
case PageIds.LiveAreaDetail:
pageType = typeof(LiveAreaDetailPage);
break;
case PageIds.MyFollows:
pageType = typeof(MyFollowsPage);
break;
default:
break;
}
Expand Down
2 changes: 1 addition & 1 deletion src/App/Controls/User/AccountPanel.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@

<local:TwoLineButton
Grid.Column="1"
Click="OnFollowButtonClickAsync"
Click="OnFollowButtonClick"
FirstLineText="{x:Bind ViewModel.FollowCount, Mode=OneWay}"
SecondLineText="{loc:LocaleLocator Name=FollowCount}" />

Expand Down
4 changes: 2 additions & 2 deletions src/App/Controls/User/AccountPanel.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ private async void OnDynamicButtonClickAsync(object sender, RoutedEventArgs e)
RequestCloseFlyout?.Invoke(this, EventArgs.Empty);
}

private async void OnFollowButtonClickAsync(object sender, RoutedEventArgs e)
private void OnFollowButtonClick(object sender, RoutedEventArgs e)
{
await AppViewModel.Instance.EnterRelatedUserViewAsync(Models.Enums.App.RelatedUserType.Follows, ViewModel.Mid.Value, ViewModel.DisplayName);
AppViewModel.Instance.SetOverlayContentId(Models.Enums.PageIds.MyFollows);
RequestCloseFlyout?.Invoke(this, EventArgs.Empty);
}

Expand Down
110 changes: 110 additions & 0 deletions src/App/Pages/Overlay/MyFollowsPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<local:AppPage
x:Class="Richasy.Bili.App.Pages.MyFollowsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:bilibili="using:Richasy.Bili.Models.BiliBili"
xmlns:controls="using:Richasy.Bili.App.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:loc="using:Richasy.Bili.Locator.Uwp"
xmlns:local="using:Richasy.Bili.App.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:uwp="using:Richasy.Bili.ViewModels.Uwp"
mc:Ignorable="d">

<Grid>

<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LayoutGroup">
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource MediumWindowThresholdWidth}" />
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="NarrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="HeaderContainer.Padding" Value="{StaticResource NarrowContainerPadding}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

<Grid x:Name="HeaderContainer" Padding="{StaticResource DefaultContainerPadding}">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Style="{StaticResource TitleTextBlockStyle}"
Margin="0,0,0,8"
HorizontalAlignment="Left"
TextTrimming="CharacterEllipsis">
<Run
FontWeight="Bold"
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
Text="{x:Bind _viewModel.UserName, Mode=OneWay}" />
<Run Text="{loc:LocaleLocator Name=FollowsSuffix}" />
</TextBlock>
<Button
x:Name="RefreshButton"
Grid.Column="1"
VerticalAlignment="Center"
Click="OnRefreshButtonClickAsync">
<controls:IconTextBlock Symbol="ArrowSync16" Text="{loc:LocaleLocator Name=Refresh}" />
</Button>
</Grid>


<muxc:NavigationView
Grid.Row="1"
IsBackButtonVisible="Collapsed"
IsPaneToggleButtonVisible="False"
IsSettingsVisible="False"
MenuItemsSource="{x:Bind _viewModel.FollowingTagCollection}"
PaneDisplayMode="Top"
SelectedItem="{x:Bind _viewModel.CurrentTag, Mode=TwoWay}">
<muxc:NavigationView.MenuItemTemplate>
<DataTemplate x:DataType="bilibili:RelatedTag">
<TextBlock Text="{x:Bind Name}" />
</DataTemplate>
</muxc:NavigationView.MenuItemTemplate>
<ScrollViewer
x:Name="ContentScrollViewer"
Grid.Row="1"
Padding="{x:Bind CoreViewModel.PageRightPadding, Mode=OneWay}"
HorizontalScrollMode="Disabled"
VerticalScrollBarVisibility="Auto">
<controls:VerticalRepeaterView
Margin="0,0,0,12"
HeaderVisibility="Collapsed"
ItemsSource="{x:Bind _viewModel.DisplayFollowingUserCollection}"
MinWideItemHeight="220"
MinWideItemWidth="180"
RequestLoadMore="OnViewRequestLoadMoreAsync">
<controls:VerticalRepeaterView.ItemTemplate>
<DataTemplate x:DataType="uwp:UserViewModel">
<controls:UserSlimCard
Click="OnUserCardClickAsync"
LevelVisibility="Collapsed"
ViewModel="{x:Bind}" />
</DataTemplate>
</controls:VerticalRepeaterView.ItemTemplate>
</controls:VerticalRepeaterView>
</ScrollViewer>
</muxc:NavigationView>

<Grid Grid.Row="1">
<controls:OverlayLoadingPanel IsBarActive="{x:Bind _viewModel.IsDeltaLoading, Mode=OneWay}" IsRingActive="{x:Bind _viewModel.IsInitializeLoading, Mode=OneWay}" />
<controls:ErrorPanel Text="{x:Bind _viewModel.ErrorText, Mode=OneWay}" Visibility="{x:Bind _viewModel.IsError, Mode=OneWay}" />
<controls:ErrorPanel Text="{loc:LocaleLocator Name=NoFollows}" Visibility="{x:Bind _viewModel.IsShowEmpty, Mode=OneWay}" />
</Grid>
</Grid>
</local:AppPage>
51 changes: 51 additions & 0 deletions src/App/Pages/Overlay/MyFollowsPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) Richasy. All rights reserved.

using System;
using System.Threading.Tasks;
using Richasy.Bili.App.Controls;
using Richasy.Bili.ViewModels.Uwp;
using Windows.UI.Xaml;

namespace Richasy.Bili.App.Pages
{
/// <summary>
/// 我的关注页面.
/// </summary>
public sealed partial class MyFollowsPage : AppPage, IRefreshPage
{
private readonly MyFollowingViewModel _viewModel = MyFollowingViewModel.Instance;

/// <summary>
/// Initializes a new instance of the <see cref="MyFollowsPage"/> class.
/// </summary>
public MyFollowsPage()
{
InitializeComponent();
Loaded += OnLoadedAsync;
}

/// <inheritdoc/>
public async Task RefreshAsync()
{
_viewModel.IsRequested = false;
await _viewModel.InitializeTagsAsync();
}

private async void OnLoadedAsync(object sender, RoutedEventArgs e)
{
if (!_viewModel.IsRequested)
{
await _viewModel.InitializeTagsAsync();
}
}

private async void OnViewRequestLoadMoreAsync(object sender, EventArgs e)
=> await _viewModel.RequestDataAsync();

private async void OnUserCardClickAsync(object sender, EventArgs e)
=> await UserView.Instance.ShowAsync((sender as UserSlimCard).ViewModel);

private async void OnRefreshButtonClickAsync(object sender, RoutedEventArgs e)
=> await RefreshAsync();
}
}
33 changes: 33 additions & 0 deletions src/Controller/Controller.Uwp/BiliController.Account.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,39 @@ public async Task RequestUserFollowsAsync(int userId, int pageNumber)
}
}

/// <summary>
/// 获取我的关注分组.
/// </summary>
/// <returns>关注分组.</returns>
public Task<List<RelatedTag>> GetMyFollowingTagsAsync()
=> _accountProvider.GetMyFollowingTagsAsync();

/// <summary>
/// 获取我的关注分组.
/// </summary>
/// <param name="tagId">分组Id.</param>
/// <param name="pageNumber">页码.</param>
/// <returns>关注分组.</returns>
public async Task GetMyFollowingTagDetailAsync(int tagId, int pageNumber)
{
ThrowWhenNetworkUnavaliable();

try
{
var result = await _accountProvider.GetMyFollowingTagDetailAsync(_accountProvider.UserId, tagId, pageNumber);
var args = new RelatedUserIterationEventArgs(result, pageNumber);
FollowsIteration?.Invoke(this, args);
}
catch (Exception ex)
{
_loggerModule.LogError(ex, pageNumber > 1);
if (pageNumber <= 1)
{
throw;
}
}
}

/// <summary>
/// 请求稍后再看视频列表.
/// </summary>
Expand Down
16 changes: 16 additions & 0 deletions src/Lib/Lib.Interfaces/IAccountProvider.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Richasy. All rights reserved.

using System.Collections.Generic;
using System.Threading.Tasks;
using Bilibili.App.Interfaces.V1;
using Richasy.Bili.Models.BiliBili;
Expand Down Expand Up @@ -106,6 +107,21 @@ public interface IAccountProvider
/// <returns>关注列表.</returns>
Task<RelatedUserResponse> GetFollowsAsync(int userId, int page);

/// <summary>
/// 获取我的关注分组.
/// </summary>
/// <returns>分组列表.</returns>
Task<List<RelatedTag>> GetMyFollowingTagsAsync();

/// <summary>
/// 获取我的关注分组详情.
/// </summary>
/// <param name="userId">指定用户的用户Id.</param>
/// <param name="tagId">分组Id.</param>
/// <param name="page">页码.</param>
/// <returns>用户列表.</returns>
Task<List<RelatedUser>> GetMyFollowingTagDetailAsync(int userId, int tagId, int page);

/// <summary>
/// 获取稍后再看列表.
/// </summary>
Expand Down
25 changes: 25 additions & 0 deletions src/Lib/Lib.Uwp/AccountProvider/AccountProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -448,5 +448,30 @@ public async Task<SearchArchiveReply> SearchUserSpaceVideoAsync(int userId, stri
var data = await _httpProvider.ParseAsync(response, SearchArchiveReply.Parser);
return data;
}

/// <inheritdoc/>
public async Task<List<RelatedTag>> GetMyFollowingTagsAsync()
{
var request = await _httpProvider.GetRequestMessageAsync(HttpMethod.Get, Account.MyFollowingTags, null, Models.Enums.RequestClientType.IOS, true);
var response = await _httpProvider.SendAsync(request);
var result = await _httpProvider.ParseAsync<ServerResponse<List<RelatedTag>>>(response);
return result.Data;
}

/// <inheritdoc/>
public async Task<List<RelatedUser>> GetMyFollowingTagDetailAsync(int userId, int tagId, int page)
{
var queryParameters = new Dictionary<string, string>
{
{ Query.TagId, tagId.ToString() },
{ Query.PageNumber, page.ToString() },
{ Query.MyId, userId.ToString() },
};

var request = await _httpProvider.GetRequestMessageAsync(HttpMethod.Get, Account.MyFollowingTagDetail, queryParameters, Models.Enums.RequestClientType.IOS, true);
var response = await _httpProvider.SendAsync(request);
var result = await _httpProvider.ParseAsync<ServerResponse<List<RelatedUser>>>(response);
return result.Data;
}
}
}
13 changes: 13 additions & 0 deletions src/Models/Models.App/Args/RelatedUserIterationEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ public RelatedUserIterationEventArgs(RelatedUserResponse response, int pageNumbe
UserId = userId;
}

/// <summary>
/// Initializes a new instance of the <see cref="RelatedUserIterationEventArgs"/> class.
/// </summary>
/// <param name="users">用户列表.</param>
/// <param name="pageNumber">页码.</param>
public RelatedUserIterationEventArgs(List<RelatedUser> users, int pageNumber)
{
List = users;
NextPageNumber = pageNumber + 1;
TotalCount = -1;
UserId = -1;
}

/// <summary>
/// 粉丝列表.
/// </summary>
Expand Down
10 changes: 10 additions & 0 deletions src/Models/Models.App/Constants/ApiConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ public static class Account
/// </summary>
public const string Follows = _apiBase + "/x/relation/followings";

/// <summary>
/// 获取我的关注分组.
/// </summary>
public const string MyFollowingTags = _apiBase + "/x/relation/tags";

/// <summary>
/// 获取我的关注分组详情.
/// </summary>
public const string MyFollowingTagDetail = _apiBase + "/x/relation/tag";

/// <summary>
/// 获取稍后再看列表.
/// </summary>
Expand Down
37 changes: 37 additions & 0 deletions src/Models/Models.BiliBili/User/RelatedUserResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,41 @@ public class RelatedUser
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "vip", Required = Required.Default)]
public Vip Vip { get; set; }
}

/// <summary>
/// 关注分组.
/// </summary>
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class RelatedTag
{
/// <summary>
/// 分组Id.
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "tagid", Required = Required.Default)]
public int TagId { get; set; }

/// <summary>
/// 名称.
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "name", Required = Required.Default)]
public string Name { get; set; }

/// <summary>
/// 总数.
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "count", Required = Required.Default)]
public int Count { get; set; }

/// <summary>
/// 说明.
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "tip", Required = Required.Default)]
public string Tip { get; set; }

/// <inheritdoc/>
public override bool Equals(object obj) => obj is RelatedTag tag && TagId == tag.TagId;

/// <inheritdoc/>
public override int GetHashCode() => 1948533646 + TagId.GetHashCode();
}
}
Loading