diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f9fefc26..87d17dd2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -116,6 +116,14 @@ jobs: run: cp C:\Package\安装教程.pdf ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_x64_Test\安装教程.pdf if: github.event.inputs.enableX64 == 'true' + - name: Remove x64 useless files + run: | + cd ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_x64_Test + rm -r -fo *.appxsym + cd Dependencies + rm -r -fo arm,arm64,x86 + if: github.event.inputs.enableX64 == 'true' + - name: Create x64 archive run: Compress-Archive -Path ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_x64_Test -DestinationPath C:\Package\${{env.AppName}}_${{github.event.inputs.version}}_x64.zip if: github.event.inputs.enableX64 == 'true' @@ -143,6 +151,14 @@ jobs: run: cp C:\Package\安装教程.pdf ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_x86_Test\安装教程.pdf if: github.event.inputs.enableX86 == 'true' + - name: Remove x86 useless files + run: | + cd ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_x86_Test + rm -r -fo *.appxsym + cd Dependencies + rm -r -fo arm,arm64,x64 + if: github.event.inputs.enableX86 == 'true' + - name: Create x86 archive run: Compress-Archive -Path ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_x86_Test -DestinationPath C:\Package\${{env.AppName}}_${{github.event.inputs.version}}_x86.zip if: github.event.inputs.enableX86 == 'true' @@ -170,6 +186,14 @@ jobs: run: cp C:\Package\安装教程.pdf ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_ARM64_Test\安装教程.pdf if: github.event.inputs.enableArm64 == 'true' + - name: Remove arm64 useless files + run: | + cd ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_ARM64_Test + rm -r -fo *.appxsym + cd Dependencies + rm -r -fo arm,x64,x86 + if: github.event.inputs.enableArm64 == 'true' + - name: Create ARM64 archive run: Compress-Archive -Path ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_ARM64_Test -DestinationPath C:\Package\${{env.AppName}}_${{github.event.inputs.version}}_ARM64.zip if: github.event.inputs.enableArm64 == 'true' @@ -197,6 +221,14 @@ jobs: run: cp C:\Package\安装教程.pdf ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_ARM_Test\安装教程.pdf if: github.event.inputs.enableArm32 == 'true' + - name: Remove arm32 useless files + run: | + cd ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_ARM_Test + rm -r -fo *.appxsym + cd Dependencies + rm -r -fo arm64,x64,x86 + if: github.event.inputs.enableArm32 == 'true' + - name: Create ARM32 archive run: Compress-Archive -Path ${{env.UWP_Project_Directory}}\AppPackages\${{env.AppName}}_${{github.event.inputs.version}}_ARM_Test -DestinationPath C:\Package\${{env.AppName}}_${{github.event.inputs.version}}_ARM.zip if: github.event.inputs.enableArm32 == 'true' diff --git a/src/BiliLite.Packages/Package.appxmanifest b/src/BiliLite.Packages/Package.appxmanifest index 53e3f790..3b9a830e 100644 --- a/src/BiliLite.Packages/Package.appxmanifest +++ b/src/BiliLite.Packages/Package.appxmanifest @@ -48,7 +48,7 @@ - + diff --git a/src/BiliLite.UWP/App.xaml.cs b/src/BiliLite.UWP/App.xaml.cs index b389d704..3f674121 100644 --- a/src/BiliLite.UWP/App.xaml.cs +++ b/src/BiliLite.UWP/App.xaml.cs @@ -61,8 +61,16 @@ private void SynchronizationContext_UnhandledException(object sender, AysncUnhan e.Handled = true; try { - logger.Log("程序运行出现错误", LogType.Error, e.Exception); - Notify.ShowMessageToast("程序出现一个错误,已记录"); + if (e.Exception is NotImplementedException) + { + logger.Log("功能未实现", LogType.Error, e.Exception); + Notify.ShowMessageToast("功能未实现"); + } + else + { + logger.Log("程序运行出现错误", LogType.Error, e.Exception); + Notify.ShowMessageToast("程序出现一个错误,已记录"); + } } catch (Exception) { @@ -73,8 +81,16 @@ private void App_UnhandledException(object sender, Windows.UI.Xaml.UnhandledExce e.Handled = true; try { - logger.Log("程序运行出现错误", LogType.Error, e.Exception); - Notify.ShowMessageToast("程序出现一个错误,已记录"); + if (e.Exception is NotImplementedException) + { + logger.Log("功能未实现", LogType.Error, e.Exception); + Notify.ShowMessageToast("功能未实现"); + } + else + { + logger.Log("程序运行出现错误", LogType.Error, e.Exception); + Notify.ShowMessageToast("程序出现一个错误,已记录"); + } } catch (Exception) { diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj index fed18a0c..0e940315 100644 --- a/src/BiliLite.UWP/BiliLite.UWP.csproj +++ b/src/BiliLite.UWP/BiliLite.UWP.csproj @@ -139,13 +139,29 @@ AttentionButton.xaml + + + DynamicItemV2Control.xaml + UserFollowingTagsFlyout.xaml + + SendDynamicV2Dialog.xaml + + + + + + + + + + @@ -194,6 +210,12 @@ + + DynamicSpacePage.xaml + + + + @@ -602,7 +624,7 @@ - + @@ -634,7 +656,7 @@ - + @@ -646,8 +668,8 @@ - - + + @@ -928,10 +950,26 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + Designer MSBuild:Compile + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -1311,6 +1349,7 @@ + diff --git a/src/BiliLite.UWP/Controls/CommentControl.xaml b/src/BiliLite.UWP/Controls/CommentControl.xaml index a2e29bce..abd64332 100644 --- a/src/BiliLite.UWP/Controls/CommentControl.xaml +++ b/src/BiliLite.UWP/Controls/CommentControl.xaml @@ -11,6 +11,7 @@ xmlns:convert="using:BiliLite.Converters" xmlns:modules="using:BiliLite.Modules" xmlns:comment="using:BiliLite.ViewModels.Comment" xmlns:common="using:BiliLite.Models.Common" + xmlns:viewModels="using:BiliLite.ViewModels" d:DesignHeight="300" d:DesignWidth="400" x:Name="CommentControlContent" @@ -30,13 +31,20 @@ + + - + @@ -185,11 +193,18 @@ - + - + @@ -204,6 +219,7 @@ + @@ -268,8 +284,6 @@ UP主觉得很赞 - - @@ -388,6 +402,30 @@ + + + + + + + + + + + + diff --git a/src/BiliLite.UWP/Controls/CommentControl.xaml.cs b/src/BiliLite.UWP/Controls/CommentControl.xaml.cs index 881e5fae..317aeaa6 100644 --- a/src/BiliLite.UWP/Controls/CommentControl.xaml.cs +++ b/src/BiliLite.UWP/Controls/CommentControl.xaml.cs @@ -16,6 +16,7 @@ using BiliLite.Models.Exceptions; using BiliLite.Models.Requests.Api; using BiliLite.Services; +using BiliLite.ViewModels; using BiliLite.ViewModels.Comment; using Microsoft.Extensions.DependencyInjection; using Microsoft.Toolkit.Uwp.UI.Controls; @@ -30,7 +31,7 @@ public sealed partial class CommentControl : UserControl #region Fields private readonly CommentApi m_commentApi; - EmoteVM emoteVM; + EmoteViewModel emoteVM; private bool m_disableShowPicture = false; private static readonly ILogger _logger = GlobalLogger.FromCurrentType(); private CommentCursor m_nextCursor; @@ -50,10 +51,10 @@ public CommentControl() { m_mapper = App.ServiceProvider.GetService(); m_viewModel = App.ServiceProvider.GetService(); + emoteVM = App.ServiceProvider.GetService(); DataContext = m_viewModel; this.InitializeComponent(); m_commentApi = new CommentApi(); - emoteVM = new EmoteVM(); Unloaded += CommentControl_Unloaded; } @@ -104,6 +105,7 @@ private async Task GetComment() result = await m_commentApi.CommentV2(m_loadCommentInfo.Oid, m_loadCommentInfo.CommentSort, m_page, m_loadCommentInfo.CommentMode, offsetStr: m_nextCursor?.PaginationReply?.NextOffset).Request(); } + if (!result.status) { throw new CustomizedErrorException("加载评论失败"); diff --git a/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs new file mode 100644 index 00000000..54f8981a --- /dev/null +++ b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs @@ -0,0 +1,75 @@ +using BiliLite.Models.Common; +using BiliLite.ViewModels.UserDynamic; +using System; +using System.Collections.Generic; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace BiliLite.Controls.DataTemplateSelectors +{ + public class UserDynamicItemV2DataTemplateSelector : DataTemplateSelector + { + private static readonly Dictionary> _dynamicTypeTemplateSelectFuncs; + + static UserDynamicItemV2DataTemplateSelector() + { + DataTemplate SelectRowTemplate(UserDynamicItemDataTemplateSelector selector, + UserDynamicItemDisplayViewModel _) => selector.OneRowTemplate; + + _dynamicTypeTemplateSelectFuncs = + new Dictionary>() + { + { + Constants.DynamicTypes.DRAW, (selector, model) => + { + if (model.Dynamic.DynDraw.Items.Count == 1) + { + return selector.Draw1x1Template; + } + return model.Dynamic.DynDraw.Items.Count == 4 ? selector.Draw2x2Template : selector.Draw3x3Template; + } + }, + { Constants.DynamicTypes.ARTICLE, (selector, model) => selector.ArticleTemplate }, + { Constants.DynamicTypes.FORWARD, (selector, model) => selector.ForwardTemplate }, + { Constants.DynamicTypes.AV, (selector, model) => selector.AvTemplate }, + { Constants.DynamicTypes.PGC, (selector, model) => selector.PgcTemplate }, + { Constants.DynamicTypes.WORD, (selector, model) => selector.WordTemplate }, + { Constants.DynamicTypes.MUSIC, (selector, model) => selector.MusicTemplate }, + { Constants.DynamicTypes.COMMON_SQUARE, (selector, model) => selector.CommonSquareTemplate }, + { Constants.DynamicTypes.LIVE_RCMD, (selector, model) => selector.LiveRcmdTemplate }, + }; + } + + public DataTemplate AvTemplate { get; set; } + + public DataTemplate PgcTemplate { get; set; } + + public DataTemplate ArticleTemplate { get; set; } + + public DataTemplate WordTemplate { get; set; } + + public DataTemplate MusicTemplate { get; set; } + + public DataTemplate ForwardTemplate { get; set; } + + public DataTemplate Draw1x1Template { get; set; } + + public DataTemplate Draw2x2Template { get; set; } + + public DataTemplate Draw3x3Template { get; set; } + + public DataTemplate CommonSquareTemplate { get; set; } + + public DataTemplate LiveRcmdTemplate { get; set; } + + public DataTemplate OtherTemplate { get; set; } + + protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) + { + var model = item as DynamicV2ItemViewModel; + var success = _dynamicTypeTemplateSelectFuncs.TryGetValue(model.CardType, out var selectFunc); + return success ? selectFunc(this, model) : OtherTemplate; + } + } +} diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml new file mode 100644 index 00000000..b638f5ad --- /dev/null +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml.cs b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml.cs new file mode 100644 index 00000000..abc86117 --- /dev/null +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml.cs @@ -0,0 +1,34 @@ +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using BiliLite.ViewModels.UserDynamic; + +// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 + +namespace BiliLite.Controls.Dynamic +{ + public sealed partial class DynamicItemV2Control : UserControl + { + public DynamicItemV2Control() + { + this.InitializeComponent(); + } + + public FrameworkElement CardContent + { + get => (FrameworkElement)GetValue(CardContentProperty); + set => SetValue(CardContentProperty, value); + } + + public static readonly DependencyProperty CardContentProperty = + DependencyProperty.Register(nameof(CardContent), typeof(FrameworkElement), typeof(DynamicItemV2Control), new PropertyMetadata(null)); + + public DynamicV2ItemViewModel ViewModel + { + get => (DynamicV2ItemViewModel)GetValue(ViewModelProperty); + set => SetValue(ViewModelProperty, value); + } + + public static readonly DependencyProperty ViewModelProperty = + DependencyProperty.Register(nameof(ViewModel), typeof(DynamicV2ItemViewModel), typeof(DynamicItemV2Control), new PropertyMetadata(null)); + } +} diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml new file mode 100644 index 00000000..f94488e4 --- /dev/null +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 长图 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 无法显示此动态,请点击以下按钮复制内容给开发者适配 + + + + + diff --git a/src/BiliLite.UWP/Converters/CountOrTextConvert.cs b/src/BiliLite.UWP/Converters/CountOrTextConvert.cs index 5f56268a..10a05b80 100644 --- a/src/BiliLite.UWP/Converters/CountOrTextConvert.cs +++ b/src/BiliLite.UWP/Converters/CountOrTextConvert.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Windows.UI.Xaml.Data; namespace BiliLite.Converters @@ -15,6 +11,11 @@ public object Convert(object value, Type targetType, object parameter, string la { return ""; } + + if (value is string valueStr) + { + value = long.Parse(valueStr); + } if (value is int || value is long) { var number = System.Convert.ToDouble(value); diff --git a/src/BiliLite.UWP/Dialogs/SendCommentDialog.xaml b/src/BiliLite.UWP/Dialogs/SendCommentDialog.xaml index 013f6060..b6777381 100644 --- a/src/BiliLite.UWP/Dialogs/SendCommentDialog.xaml +++ b/src/BiliLite.UWP/Dialogs/SendCommentDialog.xaml @@ -8,6 +8,7 @@ mc:Ignorable="d" Title="发表评论" xmlns:modules="using:BiliLite.Modules" + xmlns:viewModels="using:BiliLite.ViewModels" PrimaryButtonText="发送" SecondaryButtonText="取消" PrimaryButtonClick="ContentDialog_PrimaryButtonClick" @@ -17,7 +18,7 @@ - + diff --git a/src/BiliLite.UWP/Dialogs/SendCommentDialog.xaml.cs b/src/BiliLite.UWP/Dialogs/SendCommentDialog.xaml.cs index 6a2ff243..de6bc867 100644 --- a/src/BiliLite.UWP/Dialogs/SendCommentDialog.xaml.cs +++ b/src/BiliLite.UWP/Dialogs/SendCommentDialog.xaml.cs @@ -1,10 +1,11 @@ using BiliLite.Models.Requests.Api; -using BiliLite.Modules; using System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using BiliLite.Extensions; +using BiliLite.ViewModels; using static BiliLite.Models.Requests.Api.CommentApi; +using Microsoft.Extensions.DependencyInjection; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“内容对话框”项模板 @@ -13,14 +14,14 @@ namespace BiliLite.Dialogs public sealed partial class SendCommentDialog : ContentDialog { readonly CommentApi commentApi; - readonly EmoteVM emoteVM; + readonly EmoteViewModel emoteVM; readonly string oid; readonly CommentType commentType; public SendCommentDialog(string oid, CommentType commentType) { + emoteVM = App.ServiceProvider.GetService(); this.InitializeComponent(); commentApi = new CommentApi(); - emoteVM = new EmoteVM(); this.oid = oid; this.commentType = commentType; } diff --git a/src/BiliLite.UWP/Dialogs/SendDynamicDialog.xaml b/src/BiliLite.UWP/Dialogs/SendDynamicDialog.xaml index c968ab61..afb35b13 100644 --- a/src/BiliLite.UWP/Dialogs/SendDynamicDialog.xaml +++ b/src/BiliLite.UWP/Dialogs/SendDynamicDialog.xaml @@ -6,13 +6,14 @@ xmlns:modules="using:BiliLite.Modules" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:viewModels="using:BiliLite.ViewModels" mc:Ignorable="d"> - + @@ -30,7 +31,7 @@ - + @@ -99,13 +100,25 @@ - 转发动态 - 发表动态 + 转发动态 + 发表动态 - - @ - + + + @ + + + @@ -121,7 +134,7 @@ --> - - - + 图片上传中... - - /9张图片 - + + /9张图片 + - + diff --git a/src/BiliLite.UWP/Dialogs/SendDynamicDialog.xaml.cs b/src/BiliLite.UWP/Dialogs/SendDynamicDialog.xaml.cs index ac621a3e..a00855f6 100644 --- a/src/BiliLite.UWP/Dialogs/SendDynamicDialog.xaml.cs +++ b/src/BiliLite.UWP/Dialogs/SendDynamicDialog.xaml.cs @@ -1,12 +1,12 @@ using BiliLite.Extensions; using BiliLite.Models.Requests.Api; -using BiliLite.Modules; -using BiliLite.Modules.User; -using BiliLite.Modules.User.SendDynamic; using System; using Windows.Storage.Pickers; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; +using BiliLite.Models.Common.User.SendDynamic; +using BiliLite.ViewModels; +using BiliLite.ViewModels.User.SendDynamic; using BiliLite.ViewModels.UserDynamic; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“内容对话框”项模板 @@ -15,25 +15,22 @@ namespace BiliLite.Dialogs { public sealed partial class SendDynamicDialog : ContentDialog { - readonly EmoteVM emoteVM; - readonly AtVM atVM; - readonly SendDynamicVM sendDynamicVM; - readonly TopicVM topicVM; - public SendDynamicDialog() + readonly EmoteViewModel emoteVM; + readonly AtViewModel atVM; + readonly SendDynamicViewModel m_viewModel; + readonly TopicViewModel topicVM; + public SendDynamicDialog(SendDynamicViewModel sendDynamicViewModel, EmoteViewModel emoteViewModel, AtViewModel atViewModel, TopicViewModel topicVm) { + m_viewModel = sendDynamicViewModel; + emoteVM = emoteViewModel; + atVM = atViewModel; + topicVM = topicVm; this.InitializeComponent(); - emoteVM = new EmoteVM(); - atVM = new AtVM(); - sendDynamicVM = new SendDynamicVM(); - topicVM = new TopicVM(); } - public SendDynamicDialog(UserDynamicItemDisplayViewModel userDynamicItem) + + public void SetRepost(UserDynamicItemDisplayViewModel userDynamicItem) { - this.InitializeComponent(); - emoteVM = new EmoteVM(); - atVM = new AtVM(); - topicVM = new TopicVM(); - sendDynamicVM = new SendDynamicVM(userDynamicItem); + m_viewModel.SetRepost(userDynamicItem); } private void btn_Close_Click(object sender, RoutedEventArgs e) @@ -72,12 +69,12 @@ private void listAt_ItemClick(object sender, ItemClickEventArgs e) var at = "[@" + data.UserName + "]"; txtContent.Text += at; - sendDynamicVM.AtDisplaylist.Add(new AtDisplayModel() + m_viewModel.AddAtItem(new AtDisplayModel() { - data = data.ID, - text = at, - location = location, - length = at.Length + Data = data.ID, + Text = at, + Location = location, + Length = at.Length }); } @@ -113,13 +110,13 @@ private void TextTopic_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuery private void btn_RemovePic_Click(object sender, RoutedEventArgs e) { - sendDynamicVM.Images.Remove((sender as Button).DataContext as UploadImagesModel); - sendDynamicVM.ShowImage = gv_Pics.Items.Count > 0; + m_viewModel.Images.Remove((sender as Button).DataContext as UploadImagesModel); + m_viewModel.ShowImage = gv_Pics.Items.Count > 0; } private async void btnImage_Click(object sender, RoutedEventArgs e) { - if (sendDynamicVM.Images.Count == 9) + if (m_viewModel.Images.Count == 9) { Notify.ShowMessageToast("只能上传9张图片哦"); return; @@ -135,22 +132,22 @@ private async void btnImage_Click(object sender, RoutedEventArgs e) Windows.Storage.StorageFile file = await picker.PickSingleFileAsync(); if (file != null) { - sendDynamicVM.UploadImage(file); + m_viewModel.UploadImage(file); } } private async void btnSend_Click(object sender, RoutedEventArgs e) { - sendDynamicVM.Content = txtContent.Text; + m_viewModel.Content = txtContent.Text; bool result = false; btnSend.IsEnabled = false; - if (sendDynamicVM.IsRepost) + if (m_viewModel.IsRepost) { - result = await sendDynamicVM.SendRepost(); + result = await m_viewModel.SendRepost(); } else { - result = await sendDynamicVM.SendDynamic(); + result = await m_viewModel.SendDynamic(); } if (result) { diff --git a/src/BiliLite.UWP/Dialogs/SendDynamicV2Dialog.xaml b/src/BiliLite.UWP/Dialogs/SendDynamicV2Dialog.xaml new file mode 100644 index 00000000..ab138b78 --- /dev/null +++ b/src/BiliLite.UWP/Dialogs/SendDynamicV2Dialog.xaml @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 加载更多 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 转发动态 + 发表动态 + + + + + @ + + + + + + + + + + + + + + + + + 233 + + + + + + + 图片上传中... + + + + /9张图片 + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BiliLite.UWP/Dialogs/SendDynamicV2Dialog.xaml.cs b/src/BiliLite.UWP/Dialogs/SendDynamicV2Dialog.xaml.cs new file mode 100644 index 00000000..0073e874 --- /dev/null +++ b/src/BiliLite.UWP/Dialogs/SendDynamicV2Dialog.xaml.cs @@ -0,0 +1,164 @@ +using BiliLite.Extensions; +using BiliLite.Models.Requests.Api; +using System; +using Windows.Storage.Pickers; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using BiliLite.Models.Common.User.SendDynamic; +using BiliLite.ViewModels; +using BiliLite.ViewModels.User.SendDynamic; +using BiliLite.ViewModels.UserDynamic; + +// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“内容对话框”项模板 + +namespace BiliLite.Dialogs +{ + public sealed partial class SendDynamicV2Dialog : ContentDialog + { + readonly EmoteViewModel emoteVM; + readonly AtViewModel atVM; + readonly SendDynamicV2ViewModel m_viewModel; + readonly TopicViewModel topicVM; + + public SendDynamicV2Dialog(SendDynamicV2ViewModel sendDynamicV2ViewModel, EmoteViewModel emoteViewModel, AtViewModel atViewModel, TopicViewModel topicVm) + { + m_viewModel = sendDynamicV2ViewModel; + emoteVM = emoteViewModel; + atVM = atViewModel; + topicVM = topicVm; + this.InitializeComponent(); + } + + public void SetRepost(DynamicV2ItemViewModel userDynamicItem) + { + m_viewModel.SetRepost(userDynamicItem); + } + + private void btn_Close_Click(object sender, RoutedEventArgs e) + { + this.Hide(); + } + + private async void btnEmoji_Click(object sender, RoutedEventArgs e) + { + FaceFlyout.ShowAt(sender as Button); + if (emoteVM.Packages == null || emoteVM.Packages.Count == 0) + { + await emoteVM.GetEmote(EmoteBusiness.dynamic); + } + } + + private void gvEmoji_ItemClick(object sender, ItemClickEventArgs e) + { + txtContent.Text += (e.ClickedItem as EmotePackageItemModel).text.ToString(); + } + + private void txtContent_TextChanged(object sender, TextChangedEventArgs e) + { + txtLength.Text = (233 - txtContent.Text.Length).ToString(); + } + + private void AutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + { + atVM.Search(sender.Text); + } + + private void listAt_ItemClick(object sender, ItemClickEventArgs e) + { + var data = e.ClickedItem as AtUserModel; + var location = txtContent.Text.Length; + var at = "[@" + data.UserName + "]"; + txtContent.Text += at; + + m_viewModel.AddAtItem(new AtDisplayModel() + { + Data = data.ID, + Text = at, + Location = location, + Length = at.Length + }); + } + + private async void btnAt_Click(object sender, RoutedEventArgs e) + { + AtFlyout.ShowAt(sender as Button); + if (atVM.Users.Count == 0 && string.IsNullOrEmpty(atVM.Keyword)) + { + await atVM.GetUser(); + } + } + + private async void btnTopic_Click(object sender, RoutedEventArgs e) + { + TopicFlyout.ShowAt(sender as Button); + if (topicVM.Items == null || topicVM.Items.Count == 0) + { + await topicVM.GetTopic(); + } + } + + private void listTopic_ItemClick(object sender, ItemClickEventArgs e) + { + txtContent.Text += (e.ClickedItem as RcmdTopicModel).display; + TopicFlyout.Hide(); + } + + private void TextTopic_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + { + txtContent.Text += args.QueryText; + TopicFlyout.Hide(); + } + + private void btn_RemovePic_Click(object sender, RoutedEventArgs e) + { + m_viewModel.Images.Remove((sender as Button).DataContext as UploadImagesModel); + m_viewModel.ShowImage = gv_Pics.Items.Count > 0; + } + + private async void btnImage_Click(object sender, RoutedEventArgs e) + { + if (m_viewModel.Images.Count == 9) + { + Notify.ShowMessageToast("只能上传9张图片哦"); + return; + } + var picker = new FileOpenPicker(); + picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary; + picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail; + picker.FileTypeFilter.Add(".jpg"); + picker.FileTypeFilter.Add(".jpeg"); + picker.FileTypeFilter.Add(".png"); + picker.FileTypeFilter.Add(".bmp"); + picker.FileTypeFilter.Add(".webp"); + Windows.Storage.StorageFile file = await picker.PickSingleFileAsync(); + if (file != null) + { + m_viewModel.UploadImage(file); + } + } + + private async void btnSend_Click(object sender, RoutedEventArgs e) + { + m_viewModel.Content = txtContent.Text; + bool result = false; + btnSend.IsEnabled = false; + if (m_viewModel.IsRepost) + { + result = await m_viewModel.SendRepost(); + } + else + { + result = await m_viewModel.SendDynamic(); + } + if (result) + { + this.Hide(); + } + else + { + btnSend.IsEnabled = true; + } + + } + } +} diff --git a/src/BiliLite.UWP/Extensions/ControlsExtensions.cs b/src/BiliLite.UWP/Extensions/ControlsExtensions.cs new file mode 100644 index 00000000..955ccf7a --- /dev/null +++ b/src/BiliLite.UWP/Extensions/ControlsExtensions.cs @@ -0,0 +1,15 @@ +using BiliLite.Dialogs; +using Microsoft.Extensions.DependencyInjection; + +namespace BiliLite.Extensions +{ + public static class ControlsExtensions + { + public static IServiceCollection AddControls(this IServiceCollection services) + { + services.AddTransient(); + services.AddTransient(); + return services; + } + } +} diff --git a/src/BiliLite.UWP/Extensions/DynamicParseExtensions.cs b/src/BiliLite.UWP/Extensions/DynamicParseExtensions.cs index 3a29d00b..cbeb5e4a 100644 --- a/src/BiliLite.UWP/Extensions/DynamicParseExtensions.cs +++ b/src/BiliLite.UWP/Extensions/DynamicParseExtensions.cs @@ -5,13 +5,14 @@ using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Documents; using Windows.UI.Xaml.Markup; -using BiliLite.Controls.Dynamic; +using Bilibili.App.Dynamic.V2; using BiliLite.Models.Common; using BiliLite.Models.Common.UserDynamic; using BiliLite.Models.Dynamic; using BiliLite.Services; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Paragraph = Windows.UI.Xaml.Documents.Paragraph; namespace BiliLite.Extensions { @@ -48,6 +49,7 @@ public static UserDynamicItemDisplayShortVideoInfo ParseShortVideoInfo(JObject o return null; } } + /** * Command * UserCommand=>打开用户页面 @@ -65,7 +67,14 @@ public static UserDynamicItemDisplayShortVideoInfo ParseShortVideoInfo(JObject o /// /// /// - public static RichTextBlock UserDynamicStringToRichText(this string txt, string id, List emote, JObject extend_json) + public static RichTextBlock UserDynamicStringToRichText( + this string txt, + string id, + List emote = null, + JObject extend_json = null, + List wordNodes = null, + string title = null, + string bindingCommands= "UserDynamicItemDisplayCommands") { if (string.IsNullOrEmpty(txt)) return new RichTextBlock(); var input = txt; @@ -84,25 +93,31 @@ public static RichTextBlock UserDynamicStringToRichText(this string txt, string input = Regex.Replace(input, @"[\p{Cc}\p{Cf}]", string.Empty); //处理@ - input = HandelAtAndVote(input, txt, extend_json); + input = HandelAtAndVote(input, txt, extend_json, bindingCommands); //处理网页🔗 - input = HandelUrl(input); + input = HandelUrl(input, bindingCommands); //处理表情 input = HandelEmoji(input, emote); + input = HandelWordNodes(input, wordNodes, bindingCommands); //处理话题 - input = HandelTag(input); + input = HandelTag(input, bindingCommands); + + //标题 + var titlePara = string.IsNullOrEmpty(title) ? "" : $" {title}"; //互动抽奖🎁 - input = HandelLottery(input, id, extend_json); - input = HandelVideoID(input); + input = HandelLottery(input, id, extend_json, bindingCommands); + input = HandelVideoID(input, bindingCommands); input = input.Replace("^x$%^", "@"); //生成xaml - var xaml = string.Format(@" - {0} - ", input); + {1} +{0} + ", input, titlePara); var p = (RichTextBlock)XamlReader.Load(xaml); return p; @@ -141,12 +156,64 @@ private static string HandelEmoji(string input, List + /// 处理Word节点 + /// + private static string HandelWordNodes(string input, List nodes, string bindingCommands) + { + if (nodes == null || nodes.Count <= 0) return input; + + //替换表情 + var emotes = nodes.Where(x => x.NodeType == TextNode.Types.TextNodeType.Emote); + if (emotes.Count() != 0) + { + var matchCollection = Regex.Matches(input, @"\[.*?\]"); + foreach (Match item in matchCollection) + { + var name = item.Groups[0].Value; + var emoji = emotes.FirstOrDefault(x => + x.NodeType == TextNode.Types.TextNodeType.Emote && x.RawText.Equals(name)); + if (emoji != null) + { + input = input.Replace(item.Groups[0].Value, string.Format( + @"", + emoji.Emote.EmoteUrl, 24)); + } + } + } + + //替换AT + var ats = nodes.Where(x => x.NodeType == TextNode.Types.TextNodeType.At); + if (ats.Count() != 0) + { + foreach (var atItem in ats) + { + try + { + var run = @"" + + $@"{0}" + +"" + , atItem.RawText.Replace("@", "^x$%^"), atItem.Link.Link); + + input = input.Replace(atItem.RawText, run); + } + catch (Exception ex) + { + _logger.Error("处理At及投票信息失败", ex); + } + } + } + + return input; + } + /// /// 处理标签 /// /// /// - private static string HandelTag(string input) + private static string HandelTag(string input,string bindingCommands) { //处理话题 var avMatchCollection = Regex.Matches(input, @"\#(.*?)\#"); @@ -154,7 +221,7 @@ private static string HandelTag(string input) foreach (Match item in avMatchCollection) { if (handel.Contains(item.Groups[0].Value)) continue; - var data = @"{0}", + var data = $@"{0}", item.Groups[0].Value, item.Groups[1].Value); handel.Add(item.Groups[0].Value); input = input.Replace(item.Groups[0].Value, data); @@ -169,7 +236,7 @@ private static string HandelTag(string input) /// /// /// - private static string HandelUrl(string input) + private static string HandelUrl(string input, string bindingCommands) { var keyword = new List(); var urlMatchCollection = Regex.Matches(input, @"(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]"); @@ -180,7 +247,7 @@ private static string HandelUrl(string input) continue; } keyword.Add(item.Groups[0].Value); - var data = @"🔗网页链接", item.Groups[0].Value); input = input.Replace(item.Groups[0].Value, data); } @@ -194,8 +261,9 @@ private static string HandelUrl(string input) /// /// /// - private static string HandelAtAndVote(string input, string origin_content, JObject extendJson) + private static string HandelAtAndVote(string input, string origin_content, JObject extendJson, string bindingCommands) { + if (extendJson == null) return input; var content = origin_content; var ctrls = new List(); if (extendJson.TryGetValue("ctrl", out var ctrl)) @@ -218,7 +286,7 @@ private static string HandelAtAndVote(string input, string origin_content, JObje var d = content.Substring(item.Location, item.Length); var index = input.IndexOf(d); input = input.Remove(index, item.Length); - var run = @"{0}", d.Replace("@", "^x$%^"), item.Data); + var run = $@"{0}", d.Replace("@", "^x$%^"), item.Data); input = input.Insert(index, run); } catch (Exception ex) @@ -232,7 +300,7 @@ private static string HandelAtAndVote(string input, string origin_content, JObje var d = content.Substring(item.Location, content.Length - item.Location); var index = input.IndexOf(d); input = input.Remove(index, content.Length - item.Location); - var run = @"{0}", + var run = $@"{0}", "📊" + d, extendJson["vote"]?["vote_id"]?.ToInt32() ?? 0); input = input.Insert(index, run); } @@ -246,15 +314,16 @@ private static string HandelAtAndVote(string input, string origin_content, JObje /// /// /// - private static string HandelLottery(string input, string id, JObject extendJson) + private static string HandelLottery(string input, string id, JObject extendJson, string bindingCommands) { + if (extendJson == null) return input; if (!extendJson.ContainsKey("lott")) return input; if (input.IndexOf("互动抽奖") == 1) { input = input.Remove(1, 4); } - input = input.Insert(0, $@"🎁互动抽奖"); + input = input.Insert(0, $@"🎁互动抽奖"); return input; } @@ -263,7 +332,7 @@ private static string HandelLottery(string input, string id, JObject extendJson) /// /// /// - private static string HandelVideoID(string input) + private static string HandelVideoID(string input, string bindingCommands) { var keyword = new List(); //如果是链接就不处理了 @@ -280,7 +349,7 @@ private static string HandelVideoID(string input) keyword.Add(item.Groups[0].Value); var urlPrefix = "bilibili://video/"; var data = - $"{item.Groups[0].Value}"; input = input.Replace(item.Groups[0].Value, data); } @@ -296,7 +365,7 @@ private static string HandelVideoID(string input) keyword.Add(item.Groups[0].Value); var urlPrefix = "bilibili://video/"; var data = - $"{item.Groups[0].Value}"; input = input.Replace(item.Groups[0].Value, data); } @@ -312,7 +381,7 @@ private static string HandelVideoID(string input) keyword.Add(item.Groups[0].Value); var urlPrefix = "bilibili://article/"; var data = - $"{item.Groups[0].Value}"; input = input.Replace(item.Groups[0].Value, data); } diff --git a/src/BiliLite.UWP/Extensions/MapperExtensions.cs b/src/BiliLite.UWP/Extensions/MapperExtensions.cs index 81f52854..83488543 100644 --- a/src/BiliLite.UWP/Extensions/MapperExtensions.cs +++ b/src/BiliLite.UWP/Extensions/MapperExtensions.cs @@ -43,7 +43,12 @@ public static IServiceCollection AddMapper(this IServiceCollection services) { expression.CreateMap(); expression.CreateMap(); - expression.CreateMap(); + expression.CreateMap() + .ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Member.Uname)) + .ForMember(dest => dest.Message, opt => opt.MapFrom(src => src.Content.Message)) + .ForMember(dest => dest.Emote, opt => opt.MapFrom(src => src.Content.Emote)); + expression.CreateMap() + .ForMember(dest => dest.HotReplies, opt => opt.MapFrom(src => src.Replies)); expression.CreateMap(); expression.CreateMap(); expression.CreateMap(); @@ -120,6 +125,23 @@ public static IServiceCollection AddMapper(this IServiceCollection services) SubTitle = src.SubTitle, Title = src.Title, })); + + expression.CreateMap() + .ForMember(dest => dest.Author, + opt => opt.MapFrom(src => + src.Modules.FirstOrDefault(x => x.ModuleType == DynModuleType.ModuleAuthor).ModuleAuthor)) + .ForMember(dest => dest.AuthorForward, + opt => opt.MapFrom(src => + src.Modules.FirstOrDefault(x => x.ModuleType == DynModuleType.ModuleAuthorForward).ModuleAuthorForward)) + .ForMember(dest => dest.Dynamic, + opt => opt.MapFrom(src => + src.Modules.FirstOrDefault(x => x.ModuleType == DynModuleType.ModuleDynamic).ModuleDynamic)) + .ForMember(dest => dest.Desc, + opt => opt.MapFrom(src => + src.Modules.FirstOrDefault(x => x.ModuleType == DynModuleType.ModuleDesc).ModuleDesc)) + .ForMember(dest => dest.Stat, + opt => opt.MapFrom(src => + src.Modules.FirstOrDefault(x => x.ModuleType == DynModuleType.ModuleStat).ModuleStat)); })); services.AddSingleton(mapper); diff --git a/src/BiliLite.UWP/Extensions/StringExtensions.cs b/src/BiliLite.UWP/Extensions/StringExtensions.cs index 5bff2a1a..18052046 100644 --- a/src/BiliLite.UWP/Extensions/StringExtensions.cs +++ b/src/BiliLite.UWP/Extensions/StringExtensions.cs @@ -80,7 +80,7 @@ public static string TraditionalToSimplified(this string input) /// /// /// - public static RichTextBlock ToRichTextBlock(this string txt, JObject emote, bool isLive = false, string fontColor = null, string fontWeight = "Normal") + public static RichTextBlock ToRichTextBlock(this string txt, JObject emote, bool isLive = false, string fontColor = null, string fontWeight = "Normal",string lowProfilePrefix="") { var input = txt; try @@ -105,15 +105,21 @@ public static RichTextBlock ToRichTextBlock(this string txt, JObject emote, bool //处理av号/bv号 if (!isLive) { input = HandelVideoID(input); } + if (!string.IsNullOrEmpty(lowProfilePrefix)) + { + lowProfilePrefix = $""; + } + //生成xaml var xaml = string.Format(@" - {0} + {4}{0} ", input, isLive ? 22 : 20, fontColor == null ? "" : $"Foreground=\"{fontColor}\"", - $"FontWeight=\"{fontWeight}\""); + $"FontWeight=\"{fontWeight}\"", + lowProfilePrefix); var p = (RichTextBlock)XamlReader.Load(xaml); return p; } @@ -157,6 +163,7 @@ public static string SubstringCommentText(this string input,int length) matches.Add(index, value); } var newInput = regex.Replace(input, ""); + if (newInput.Length < length) return input; var output = newInput.Substring(0, length); foreach (var pair in matches) { diff --git a/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs b/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs index a188a8a1..1b309f2d 100644 --- a/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs +++ b/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs @@ -1,8 +1,11 @@ -using BiliLite.ViewModels.Comment; +using BiliLite.ViewModels; +using BiliLite.ViewModels.Comment; using BiliLite.ViewModels.Download; using BiliLite.ViewModels.Home; using BiliLite.ViewModels.Live; using BiliLite.ViewModels.User; +using BiliLite.ViewModels.User.SendDynamic; +using BiliLite.ViewModels.UserDynamic; using Microsoft.Extensions.DependencyInjection; namespace BiliLite.Extensions @@ -25,6 +28,12 @@ public static IServiceCollection AddViewModels(this IServiceCollection services) services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); return services; } } diff --git a/src/BiliLite.UWP/MainPage.xaml.cs b/src/BiliLite.UWP/MainPage.xaml.cs index 4050c59a..6a47ea94 100644 --- a/src/BiliLite.UWP/MainPage.xaml.cs +++ b/src/BiliLite.UWP/MainPage.xaml.cs @@ -269,7 +269,7 @@ private void tabView_TabItemsChanged(TabView sender, IVectorChangedEventArgs arg private void TabView_OnPreviewKeyDown(object sender, KeyRoutedEventArgs e) { - if(e.Key == VirtualKey.Space) + if(e.Key == VirtualKey.Space && e.OriginalSource.GetType()!= typeof(TextBox)) e.Handled = true; } } diff --git a/src/BiliLite.UWP/Models/Builders/DynamicItemDisplayModelBuilder.cs b/src/BiliLite.UWP/Models/Builders/DynamicItemDisplayModelBuilder.cs index 6ce593f4..821b3282 100644 --- a/src/BiliLite.UWP/Models/Builders/DynamicItemDisplayModelBuilder.cs +++ b/src/BiliLite.UWP/Models/Builders/DynamicItemDisplayModelBuilder.cs @@ -191,7 +191,10 @@ public DynamicItemDisplayModelBuilder SetContent(JObject card, JObject extendJso if (!string.IsNullOrEmpty(content)) { m_displayViewModel.ContentStr = content; - m_displayViewModel.Content = content.UserDynamicStringToRichText(m_cardModel.desc.dynamic_id, m_cardModel.display?.emoji_info?.emoji_details, extendJson); + m_displayViewModel.Content = content.UserDynamicStringToRichText( + m_cardModel.desc.dynamic_id, + emote: m_cardModel.display?.emoji_info?.emoji_details, + extend_json: extendJson); } else { diff --git a/src/BiliLite.UWP/Models/Common/Comment/HotReply.cs b/src/BiliLite.UWP/Models/Common/Comment/HotReply.cs new file mode 100644 index 00000000..8195e1e1 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/Comment/HotReply.cs @@ -0,0 +1,43 @@ +using System; +using Windows.UI.Xaml.Controls; +using BiliLite.Extensions; +using BiliLite.Services; +using Newtonsoft.Json.Linq; + +namespace BiliLite.Models.Common.Comment +{ + public class HotReply + { + private static readonly ILogger _logger = GlobalLogger.FromCurrentType(); + + public string UserName { get; set; } + + public string Message { get; set; } + + public JObject Emote { get; set; } + + public RichTextBlock Content + { + get + { + try + { + if (Message.Length <= 50) + { + return $"{Message}" + .ToRichTextBlock(Emote, lowProfilePrefix: $"{UserName}: "); + } + + var substringMsg = $"{Message.SubstringCommentText(50)}..."; + + return substringMsg.ToRichTextBlock(Emote, lowProfilePrefix: $"{UserName}: "); + } + catch (Exception ex) + { + _logger.Error("热门回复加载失败", ex); + return new RichTextBlock(); + } + } + } + } +} diff --git a/src/BiliLite.UWP/Models/Common/Constants.cs b/src/BiliLite.UWP/Models/Common/Constants.cs index 0d05e216..6fce164c 100644 --- a/src/BiliLite.UWP/Models/Common/Constants.cs +++ b/src/BiliLite.UWP/Models/Common/Constants.cs @@ -81,5 +81,26 @@ public static class Images /// public const string MY_ICON_IMAGE = "ms-appx:///Assets/Icon/我的.png"; } + + public static class DynamicTypes + { + public const string AV = "Av"; + + public const string PGC = "Pgc"; + + public const string WORD = "Word"; + + public const string DRAW = "Draw"; + + public const string MUSIC = "Music"; + + public const string ARTICLE = "Article"; + + public const string FORWARD = "Forward"; + + public const string COMMON_SQUARE = "CommonSquare"; + + public const string LIVE_RCMD = "LiveRcmd"; + } } } diff --git a/src/BiliLite.UWP/Models/Common/Home/DefaultHomeNavItems.cs b/src/BiliLite.UWP/Models/Common/Home/DefaultHomeNavItems.cs index 60e26296..829c070c 100644 --- a/src/BiliLite.UWP/Models/Common/Home/DefaultHomeNavItems.cs +++ b/src/BiliLite.UWP/Models/Common/Home/DefaultHomeNavItems.cs @@ -119,6 +119,30 @@ public static List GetDefaultHideHomeNavItems() Title = "新标签页", NeedLogin = false, Show = true + }, + new HomeNavItem() + { + Icon = FontAwesome5.EFontAwesomeIcon.Regular_PlayCircle, + Page = typeof(Pages.User.WatchlaterPage), + Title = "稍后再看", + NeedLogin = true, + Show = false + }, + new HomeNavItem() + { + Icon = FontAwesome5.EFontAwesomeIcon.Solid_History, + Page = typeof(Pages.User.HistoryPage), + Title = "历史记录", + NeedLogin = true, + Show = false + }, + new HomeNavItem() + { + Icon = FontAwesome5.EFontAwesomeIcon.Regular_Star, + Page = typeof(Pages.User.FavoritePage), + Title = "我的收藏", + NeedLogin = true, + Show = false } }; } diff --git a/src/BiliLite.UWP/Models/Common/SettingConstants.cs b/src/BiliLite.UWP/Models/Common/SettingConstants.cs index 64812d2e..84ac4dec 100644 --- a/src/BiliLite.UWP/Models/Common/SettingConstants.cs +++ b/src/BiliLite.UWP/Models/Common/SettingConstants.cs @@ -107,6 +107,16 @@ public class UI /// 默认折叠评论长度 /// public const int COMMENT_SHRINK_DEFAULT_LENGTH = 75; + + /// + /// 显示评论热门回复 + /// + public const string SHOW_HOT_REPLIES = "ShowHotReplies"; + + /// + /// 显示评论热门回复默认选项 + /// + public const bool DEFAULT_SHOW_HOT_REPLIES = true; } public class Account diff --git a/src/BiliLite.UWP/Models/Common/User/SendDynamic/AtDisplayModel.cs b/src/BiliLite.UWP/Models/Common/User/SendDynamic/AtDisplayModel.cs new file mode 100644 index 00000000..52280f66 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/User/SendDynamic/AtDisplayModel.cs @@ -0,0 +1,13 @@ +namespace BiliLite.Models.Common.User.SendDynamic +{ + public class AtDisplayModel + { + public long Data { get; set; } + + public string Text { get; set; } + + public int Location { get; set; } + + public int Length { get; set; } + } +} \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/User/SendDynamic/AtModel.cs b/src/BiliLite.UWP/Models/Common/User/SendDynamic/AtModel.cs new file mode 100644 index 00000000..41fa02ea --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/User/SendDynamic/AtModel.cs @@ -0,0 +1,13 @@ +namespace BiliLite.Models.Common.User.SendDynamic +{ + public class AtModel + { + public string Data { get; set; } + + public int Location { get; set; } + + public int Length { get; set; } + + public int Type { get; set; } = 1; + } +} \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/User/SendDynamic/AtUserModel.cs b/src/BiliLite.UWP/Models/Common/User/SendDynamic/AtUserModel.cs new file mode 100644 index 00000000..84460808 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/User/SendDynamic/AtUserModel.cs @@ -0,0 +1,10 @@ +namespace BiliLite.Models.Common.User.SendDynamic +{ + public class AtUserModel + { + public long ID { get; set; } + public string UserName { get; set; } + public string Face { get; set; } + public string Display { get { return "@" + UserName; } } + } +} \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/User/SendDynamic/RcmdTopicModel.cs b/src/BiliLite.UWP/Models/Common/User/SendDynamic/RcmdTopicModel.cs new file mode 100644 index 00000000..b9fde95f --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/User/SendDynamic/RcmdTopicModel.cs @@ -0,0 +1,13 @@ +namespace BiliLite.Models.Common.User.SendDynamic +{ + public class RcmdTopicModel + { + public int topic_id { get; set; } + public string topic_name { get; set; } + public int is_activity { get; set; } + public string display + { + get { return "#" + topic_name + "#"; } + } + } +} \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/User/SendDynamic/SendImagesModel.cs b/src/BiliLite.UWP/Models/Common/User/SendDynamic/SendImagesModel.cs new file mode 100644 index 00000000..f89142a2 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/User/SendDynamic/SendImagesModel.cs @@ -0,0 +1,18 @@ +using Newtonsoft.Json; + +namespace BiliLite.Models.Common.User.SendDynamic +{ + public class SendImagesModel + { + [JsonProperty("img_height")] + public int ImgHeight { get; set; } + [JsonProperty("img_src")] + public string ImgSrc { get; set; } + + [JsonProperty("img_size")] + public double ImgSize { get; set; } + + [JsonProperty("img_width")] + public int ImgWidth { get; set; } + } +} \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/User/SendDynamic/UploadImagesModel.cs b/src/BiliLite.UWP/Models/Common/User/SendDynamic/UploadImagesModel.cs new file mode 100644 index 00000000..b5ee47d4 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/User/SendDynamic/UploadImagesModel.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; + +namespace BiliLite.Models.Common.User.SendDynamic +{ + public class UploadImagesModel + { + [JsonProperty("image_height")] + public int ImageHeight { get; set; } + + [JsonProperty("image_url")] + public string ImageUrl { get; set; } + + [JsonProperty("image_size")] + public double ImageSize { get; set; } + + public string Image => ImageUrl + "@120w_120h_1e_1c.jpg"; + + [JsonProperty("image_width")] + public int ImageWidth { get; set; } + } +} \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/UserDynamic/DynLiveInfo.cs b/src/BiliLite.UWP/Models/Common/UserDynamic/DynLiveInfo.cs new file mode 100644 index 00000000..42028a00 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/UserDynamic/DynLiveInfo.cs @@ -0,0 +1,39 @@ +using Newtonsoft.Json; + +namespace BiliLite.Models.Common.UserDynamic +{ + public class DynLiveInfo + { + [JsonProperty("live_play_info")] + public DynLivePlayInfo PlayInfo { get; set; } + } + + public class DynLivePlayInfo + { + [JsonProperty("room_id")] + public long RoomId { get; set; } + + [JsonProperty("uid")] + public long UserId { get; set; } + + [JsonProperty("live_status")] + public int LiveStatus { get; set; } + + public string Title { get; set; } + + public string Cover { get; set; } + + [JsonProperty("area_name")] + public string AreaName { get; set; } + + [JsonProperty("watched_show")] + public DynLiveWatchedShow WatchedShow { get; set; } + } + + public class DynLiveWatchedShow + { + + [JsonProperty("text_large")] + public string TextLarge { get; set; } + } +} diff --git a/src/BiliLite.UWP/Models/Common/UserDynamic/UserDynamicItemDisplayImageInfo.cs b/src/BiliLite.UWP/Models/Common/UserDynamic/UserDynamicItemDisplayImageInfo.cs index 5e329cae..bf703b1d 100644 --- a/src/BiliLite.UWP/Models/Common/UserDynamic/UserDynamicItemDisplayImageInfo.cs +++ b/src/BiliLite.UWP/Models/Common/UserDynamic/UserDynamicItemDisplayImageInfo.cs @@ -11,9 +11,9 @@ public class UserDynamicItemDisplayImageInfo public string ImageUrl { get; set; } - public int Width { get; set; } + public long Width { get; set; } - public int Height { get; set; } + public long Height { get; set; } public List AllImages { get; set; } diff --git a/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs b/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs index 7ea075ec..f5da85fa 100644 --- a/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs +++ b/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs @@ -63,7 +63,9 @@ public ApiModel DynamicDetail(string id) //使用Web的API if (SettingService.Account.Logined) { - api.parameter += $"&access_key={SettingService.Account.AccessKey}"; + api.parameter += "&"; + api.parameter += ApiHelper.MustParameter(AppKey, true); + api.parameter += ApiHelper.GetSign(api.parameter, AppKey); } return api; @@ -135,6 +137,24 @@ public ApiModel SpaceHistory(string mid, string dynamic_id = "") return api; } + + public ApiModel SpaceHistoryV2(string mid, string offset = "") + { + var api = new ApiModel() + { + method = RestSharp.Method.Get, + baseUrl = $"https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space", + parameter = $"offset={offset}&host_mid={mid}", + need_cookie = true, + }; + //if (SettingService.Account.Logined) + //{ + // api.parameter += ApiHelper.MustParameter(AppKey, true); + // api.parameter += ApiHelper.GetSign(api.parameter, AppKey); + //} + + return api; + } /// /// 推荐话题 /// diff --git a/src/BiliLite.UWP/Modules/User/SendDynamic/SendDynamicVM.cs b/src/BiliLite.UWP/Modules/User/SendDynamic/SendDynamicVM.cs deleted file mode 100644 index 85a280f8..00000000 --- a/src/BiliLite.UWP/Modules/User/SendDynamic/SendDynamicVM.cs +++ /dev/null @@ -1,331 +0,0 @@ -using BiliLite.Models; -using BiliLite.Models.Requests.Api.User; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using RestSharp; -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Runtime.InteropServices.WindowsRuntime; -using System.Threading.Tasks; -using Windows.Storage; -using Windows.Storage.Streams; -using BiliLite.Extensions; -using BiliLite.Models.Responses; -using BiliLite.Models.Common; -using BiliLite.Services; -using BiliLite.ViewModels.UserDynamic; - -namespace BiliLite.Modules.User -{ - public class SendDynamicVM : IModules - { - private static readonly ILogger logger = GlobalLogger.FromCurrentType(); - - readonly DynamicAPI dynamicAPI; - public SendDynamicVM() - { - dynamicAPI = new DynamicAPI(); - Images = new ObservableCollection(); - } - public SendDynamicVM(UserDynamicItemDisplayViewModel repostInfo) - { - dynamicAPI = new DynamicAPI(); - RepostInfo = repostInfo; - IsRepost = true; - } - private bool _IsRepost = false; - public bool IsRepost - { - get { return _IsRepost; } - set { _IsRepost = value; DoPropertyChanged("IsRepost"); } - } - - public UserDynamicItemDisplayViewModel RepostInfo { get; set; } - - private string _Content = ""; - public string Content - { - get { return _Content; } - set { _Content = value; DoPropertyChanged("Content"); DoPropertyChanged("Count"); } - } - - private ObservableCollection _images; - - public ObservableCollection Images - { - get { return _images; } - set { _images = value; DoPropertyChanged("Images"); } - } - private bool _uploading; - - public bool Uploading - { - get { return _uploading; } - set { _uploading = value; DoPropertyChanged("Uploading"); } - } - - private bool _showImage = false; - - public bool ShowImage - { - get { return _showImage; } - set { _showImage = value; DoPropertyChanged("ShowImage"); } - } - public List AtDisplaylist = new List(); - public List Atlist = new List(); - public async void UploadImage(StorageFile file) - { - try - { - - Uploading = true; - var api = dynamicAPI.UploadImage(); - - - IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read); - var bytes = new byte[fileStream.Size]; - await fileStream.ReadAsync(bytes.AsBuffer(), (uint)fileStream.Size, Windows.Storage.Streams.InputStreamOptions.None); - var client = new RestClient(api.url); - var request = new RestRequest(); - request.Method = Method.Post; - request.AddParameter("biz", "draw"); - request.AddParameter("category", "daily"); - request.AddFile("file_up", bytes, file.Name); - RestResponse response = await client.ExecuteAsync(request); - var content = response.Content; - - ApiDataModel result = JsonConvert.DeserializeObject>(content); - if (result.code == 0) - { - result.data.image_size = (await file.GetBasicPropertiesAsync()).Size / 1024; - Images.Add(result.data); - } - else - { - Notify.ShowMessageToast(result.message); - } - } - catch (Exception ex) - { - logger.Log("图片上传失败", LogType.Fatal, ex); - Notify.ShowMessageToast("图片上传失败"); - } - finally - { - Uploading = false; - ShowImage = Images.Count > 0; - - } - } - - /// - /// 转发 - /// - public async Task SendRepost() - { - var ctrl = "[]"; - var at_uids = ""; - Atlist.Clear(); - - if (AtDisplaylist.Count != 0) - { - - foreach (var item in AtDisplaylist) - { - if (Content.Contains(item.text)) - { - Atlist.Add(new AtModel() - { - data = item.data.ToString(), - length = item.length - 2, - location = Content.IndexOf(item.text), - type = 1 - }); - var d = item.text.Replace("[", "").Replace("]", ""); - Content = Content.Replace(item.text, d); - at_uids += item.data.ToString() + ","; - } - } - ctrl = JsonConvert.SerializeObject(Atlist); - at_uids = at_uids.Remove(at_uids.Length - 1, 1); - AtDisplaylist.Clear(); - } - if (Content == "") - { - Content = "转发动态"; - } - try - { - - HttpResults httpResults = await dynamicAPI.RepostDynamic(RepostInfo.DynamicID, Content, at_uids, ctrl).Request(); - if (httpResults.status) - { - var data = await httpResults.GetData(); - if (data.code == 0) - { - - Notify.ShowMessageToast("转发成功"); - AtDisplaylist.Clear(); - return true; - } - else - { - - Notify.ShowMessageToast("发表动态失败:" + data.message); - return false; - } - } - else - { - - Notify.ShowMessageToast(httpResults.message); - return false; - } - - } - catch (Exception ex) - { - Notify.ShowMessageToast("转发动态失败" + ex.Message); - logger.Log("转发动态失败", LogType.Error, ex); - return false; - } - - } - public async Task SendDynamic() - { - if (Content.Trim().Length == 0) - { - Notify.ShowMessageToast("不能发送空白动态"); - return false; - } - - var ctrl = "[]"; - var at_uids = ""; - Atlist.Clear(); - var txt = Content; - if (AtDisplaylist.Count != 0) - { - foreach (var item in AtDisplaylist) - { - if (txt.Contains(item.text)) - { - Atlist.Add(new AtModel() - { - data = item.data.ToString(), - length = item.length - 2, - location = txt.IndexOf(item.text), - type = 1 - }); - var d = item.text.Replace("[", "").Replace("]", ""); - txt = txt.Replace(item.text, d); - at_uids += item.data.ToString() + ","; - } - } - ctrl = JsonConvert.SerializeObject(Atlist); - at_uids = at_uids.Remove(at_uids.Length - 1, 1); - - } - - List send_pics = new List(); - foreach (var item in Images) - { - send_pics.Add(new SendImagesModel() - { - img_height = item.image_height, - img_size = item.image_size, - img_src = item.image_url, - img_width = item.image_width - }); - } - var imgStr = JsonConvert.SerializeObject(send_pics); - try - { - HttpResults httpResults; - if (send_pics.Count == 0) - { - httpResults = await dynamicAPI.CreateDynamicText(txt, at_uids, ctrl).Request(); - } - else - { - httpResults = await dynamicAPI.CreateDynamicPhoto(imgStr, txt, at_uids, ctrl).Request(); - } - if (httpResults.status) - { - var data = await httpResults.GetData(); - if (data.code == 0) - { - - Notify.ShowMessageToast("发表动态成功"); - AtDisplaylist.Clear(); - return true; - } - else - { - - Notify.ShowMessageToast("发表动态失败:" + data.message); - return false; - } - } - else - { - Notify.ShowMessageToast(httpResults.message); - return false; - } - - } - catch (Exception ex) - { - - Notify.ShowMessageToast("发表动态发生错误"); - logger.Log("发表动态失败", LogType.Error, ex); - return false; - } - - } - } - - public class UploadImagesModel - { - public int image_height { get; set; } - public string image_url { get; set; } - - public double image_size { get; set; } - - public string image - { - get - { - return image_url + "@120w_120h_1e_1c.jpg"; - } - } - public int image_width { get; set; } - - } - public class SendImagesModel - { - - - public int img_height { get; set; } - public string img_src { get; set; } - - public double img_size { get; set; } - public int img_width { get; set; } - - } - public class AtModel - { - public string data { get; set; } - public int location { get; set; } - public int length { get; set; } - public int type { get; set; } = 1; - } - public class AtDisplayModel - { - public long data { get; set; } - public string text { get; set; } - public int location { get; set; } - public int length { get; set; } - } - -} diff --git a/src/BiliLite.UWP/Modules/User/WatchLaterVM.cs b/src/BiliLite.UWP/Modules/User/WatchLaterVM.cs index fe9b66ba..f1b97ab4 100644 --- a/src/BiliLite.UWP/Modules/User/WatchLaterVM.cs +++ b/src/BiliLite.UWP/Modules/User/WatchLaterVM.cs @@ -5,12 +5,9 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; -using System.Text; using System.Threading.Tasks; using System.Windows.Input; using BiliLite.Extensions; -using BiliLite.Models.Common; using BiliLite.Services; namespace BiliLite.Modules.User @@ -39,6 +36,7 @@ public WatchLaterVM() { watchLaterAPI = new WatchLaterAPI(); AddCommand = new RelayCommand(AddToWatchlater); + AddCommandWithAvId = new RelayCommand(AddToWatchlater); RefreshCommand = new RelayCommand(Refresh); CleanCommand = new RelayCommand(Clear); DeleteCommand = new RelayCommand(Del); @@ -46,10 +44,20 @@ public WatchLaterVM() } public ICommand AddCommand { get; private set; } + + public ICommand AddCommandWithAvId { get; private set; } + public ICommand CleanCommand { get; private set; } public ICommand CleanViewedCommand { get; private set; } public ICommand DeleteCommand { get; private set; } public ICommand RefreshCommand { get; private set; } + + + public async void AddToWatchlater(long aid) + { + AddToWatchlater(aid.ToString()); + } + public async void AddToWatchlater(string aid) { try diff --git a/src/BiliLite.UWP/Pages/HomePage.xaml.cs b/src/BiliLite.UWP/Pages/HomePage.xaml.cs index 7347317b..ee619c6f 100644 --- a/src/BiliLite.UWP/Pages/HomePage.xaml.cs +++ b/src/BiliLite.UWP/Pages/HomePage.xaml.cs @@ -317,6 +317,8 @@ private async void SearchBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTe { if (args.Reason != AutoSuggestionBoxTextChangeReason.UserInput) return; var text = sender.Text; + text = text.TrimEnd(); + if (string.IsNullOrWhiteSpace(text)) return; var suggestSearchContents = await new SearchService().GetSearchSuggestContents(text); if (m_viewModel.SuggestSearchContents == null) { diff --git a/src/BiliLite.UWP/Pages/SearchPage.xaml.cs b/src/BiliLite.UWP/Pages/SearchPage.xaml.cs index 5b9c6360..3bc486c9 100644 --- a/src/BiliLite.UWP/Pages/SearchPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/SearchPage.xaml.cs @@ -259,6 +259,8 @@ private async void txtKeyword_TextChanged(AutoSuggestBox sender, AutoSuggestBoxT { if (args.Reason != AutoSuggestionBoxTextChangeReason.UserInput) return; var text = sender.Text; + text = text.TrimEnd(); + if (string.IsNullOrWhiteSpace(text)) return; var suggestSearchContents = await new SearchService().GetSearchSuggestContents(text); if (searchVM.SuggestSearchContents == null) { diff --git a/src/BiliLite.UWP/Pages/SettingPage.xaml b/src/BiliLite.UWP/Pages/SettingPage.xaml index bcb54965..505e8a8e 100644 --- a/src/BiliLite.UWP/Pages/SettingPage.xaml +++ b/src/BiliLite.UWP/Pages/SettingPage.xaml @@ -182,6 +182,11 @@ + + 展示评论热门回复 + + + 新窗口打开图片预览 diff --git a/src/BiliLite.UWP/Pages/SettingPage.xaml.cs b/src/BiliLite.UWP/Pages/SettingPage.xaml.cs index 554decdc..d3d8c23a 100644 --- a/src/BiliLite.UWP/Pages/SettingPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/SettingPage.xaml.cs @@ -232,6 +232,16 @@ private void LoadUI() }; }; + // 展示评论热门回复 + swShowHotReplies.IsOn = SettingService.GetValue(SettingConstants.UI.SHOW_HOT_REPLIES, SettingConstants.UI.DEFAULT_SHOW_HOT_REPLIES); + swShowHotReplies.Loaded += (sender, e) => + { + swShowHotReplies.Toggled += (obj, args) => + { + SettingService.SetValue(SettingConstants.UI.SHOW_HOT_REPLIES, swShowHotReplies.IsOn); + }; + }; + //动态显示 cbDynamicDisplayMode.SelectedIndex = SettingService.GetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0); cbDynamicDisplayMode.Loaded += new RoutedEventHandler((sender, e) => diff --git a/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml b/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml new file mode 100644 index 00000000..8ba235e1 --- /dev/null +++ b/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + Visible + + + + + Collapsed + + + + + + + + + + + + + + + Collapsed + + + + + Visible + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml.cs b/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml.cs new file mode 100644 index 00000000..4a21e0bb --- /dev/null +++ b/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml.cs @@ -0,0 +1,160 @@ +using System.Linq; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media.Animation; +using Windows.UI.Xaml.Navigation; +using BiliLite.Models.Common; +using BiliLite.Models.Common.Comment; +using BiliLite.Services; +using BiliLite.ViewModels.UserDynamic; +using Microsoft.Extensions.DependencyInjection; +using BiliLite.Models.Requests.Api; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace BiliLite.Pages.User +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class DynamicSpacePage : Page + { + private readonly UserDynamicSpaceViewModel m_viewModel; + private bool m_isStaggered = false; + + public DynamicSpacePage() + { + m_viewModel = App.ServiceProvider.GetRequiredService(); + m_viewModel.OpenCommentEvent += UserDynamicViewModelOpenCommentEvent; + this.InitializeComponent(); + } + + private void SetStaggered() + { + var staggered = SettingService.GetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0) == 1; + if (staggered != m_isStaggered) + { + m_isStaggered = staggered; + if (staggered) + { + SetGridCore(); + } + else + { + SetListCore(); + } + } + } + + private void SetGridCore() + { + m_isStaggered = true; + BtnGrid.Visibility = Visibility.Collapsed; + BtnList.Visibility = Visibility.Visible; + //XAML + ListDyn.ItemsPanel = (ItemsPanelTemplate)this.Resources["GridPanel"]; + } + + private void SetListCore() + { + m_isStaggered = false; + //右下角按钮 + BtnGrid.Visibility = Visibility.Visible; + BtnList.Visibility = Visibility.Collapsed; + //XAML + ListDyn.ItemsPanel = (ItemsPanelTemplate)this.Resources["ListPanel"]; + } + + protected override async void OnNavigatedTo(NavigationEventArgs e) + { + SetStaggered(); + m_viewModel.UserId = e.Parameter as string; + await m_viewModel.GetDynamicItems(); + } + + private async void BtnRefreshDynamic_OnClick(object sender, RoutedEventArgs e) + { + await m_viewModel.GetDynamicItems(); + } + + private void BtnTop_OnClick(object sender, RoutedEventArgs e) + { + ListDyn.ScrollIntoView(ListDyn.Items.FirstOrDefault()); + } + + private void BtnList_OnClick(object sender, RoutedEventArgs e) + { + SettingService.SetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0); + SetListCore(); + } + + private void BtnGrid_OnClick(object sender, RoutedEventArgs e) + { + SettingService.SetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 1); + SetGridCore(); + } + + private void CloseCommentCore() + { + var storyboard = (Storyboard)this.Resources["HideComment"]; + storyboard.Begin(); + } + + + private void UserDynamicViewModelOpenCommentEvent(object sender, DynamicV2ItemViewModel e) + { + CommentApi.CommentType commentType = CommentApi.CommentType.Dynamic; + var id = e.Extend.BusinessId; + switch (e.CardType) + { + case Constants.DynamicTypes.DRAW: + commentType = CommentApi.CommentType.Photo; + break; + case Constants.DynamicTypes.AV: + commentType = CommentApi.CommentType.Video; + break; + case Constants.DynamicTypes.PGC: + id = e.Dynamic.DynPgc.Aid.ToString(); + commentType = CommentApi.CommentType.Video; + break; + //case UserDynamicDisplayType.ShortVideo: + // commentType = CommentApi.CommentType.MiniVideo; + // break; + case Constants.DynamicTypes.MUSIC: + commentType = CommentApi.CommentType.Song; + break; + case Constants.DynamicTypes.ARTICLE: + commentType = CommentApi.CommentType.Article; + break; + //case UserDynamicDisplayType.MediaList: + // if (e.OneRowInfo.Tag != "收藏夹") + // commentType = CommentApi.CommentType.Video; + // break; + default: + id = e.Extend.DynIdStr; + break; + } + + OpenCommentCore(id, (int)commentType, CommentApi.CommentSort.Hot); + } + + private void OpenCommentCore(string oid, int commentMode, CommentApi.CommentSort commentSort) + { + Comment.LoadComment(new LoadCommentInfo() + { + CommentMode = commentMode, + CommentSort = commentSort, + Oid = oid, + IsDialog = true + }); + var storyboard = (Storyboard)this.Resources["ShowComment"]; + storyboard.Begin(); + } + + private void CommentPanel_OnTapped(object sender, TappedRoutedEventArgs e) + { + CloseCommentCore(); + } + } +} diff --git a/src/BiliLite.UWP/Pages/UserInfoPage.xaml b/src/BiliLite.UWP/Pages/UserInfoPage.xaml index 3aeb89e7..a8f7c298 100644 --- a/src/BiliLite.UWP/Pages/UserInfoPage.xaml +++ b/src/BiliLite.UWP/Pages/UserInfoPage.xaml @@ -288,49 +288,14 @@ - + 动态 - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/src/BiliLite.UWP/Pages/UserInfoPage.xaml.cs b/src/BiliLite.UWP/Pages/UserInfoPage.xaml.cs index 3c2bf9b3..b0df033f 100644 --- a/src/BiliLite.UWP/Pages/UserInfoPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/UserInfoPage.xaml.cs @@ -118,7 +118,7 @@ private void UserDynamicViewModelOpenCommentEvent(object sender, UserDynamicItem protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - SetStaggered(); + //SetStaggered(); if (e.NavigationMode == NavigationMode.New) { var mid = ""; @@ -237,49 +237,49 @@ private void pivotRight_SelectionChanged(object sender, SelectionChangedEventArg } } - void SetStaggered() - { - var staggered = SettingService.GetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0) == 1; - if (staggered != IsStaggered) - { - IsStaggered = staggered; - if (staggered) - { - btnGrid_Click(this, null); - } - else - { - btnList_Click(this, null); - } - } - } + //void SetStaggered() + //{ + // var staggered = SettingService.GetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0) == 1; + // if (staggered != IsStaggered) + // { + // IsStaggered = staggered; + // if (staggered) + // { + // btnGrid_Click(this, null); + // } + // else + // { + // btnList_Click(this, null); + // } + // } + //} - private void btnGrid_Click(object sender, RoutedEventArgs e) - { - SettingService.SetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 1); - IsStaggered = true; - btnGrid.Visibility = Visibility.Collapsed; - btnList.Visibility = Visibility.Visible; - //XAML - list.ItemsPanel = (ItemsPanelTemplate)this.Resources["GridPanel"]; - } + //private void btnGrid_Click(object sender, RoutedEventArgs e) + //{ + // SettingService.SetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 1); + // IsStaggered = true; + // btnGrid.Visibility = Visibility.Collapsed; + // btnList.Visibility = Visibility.Visible; + // //XAML + // list.ItemsPanel = (ItemsPanelTemplate)this.Resources["GridPanel"]; + //} - private void btnList_Click(object sender, RoutedEventArgs e) - { - IsStaggered = false; - //右下角按钮 - btnGrid.Visibility = Visibility.Visible; - btnList.Visibility = Visibility.Collapsed; - //设置 - SettingService.SetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0); - //XAML - list.ItemsPanel = (ItemsPanelTemplate)this.Resources["ListPanel"]; - } + //private void btnList_Click(object sender, RoutedEventArgs e) + //{ + // IsStaggered = false; + // //右下角按钮 + // btnGrid.Visibility = Visibility.Visible; + // btnList.Visibility = Visibility.Collapsed; + // //设置 + // SettingService.SetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0); + // //XAML + // list.ItemsPanel = (ItemsPanelTemplate)this.Resources["ListPanel"]; + //} - private void btnTop_Click(object sender, RoutedEventArgs e) - { - list.ScrollIntoView(list.Items[0]); - } + //private void btnTop_Click(object sender, RoutedEventArgs e) + //{ + // list.ScrollIntoView(list.Items[0]); + //} private async void pivot_SelectionChanged(object sender, SelectionChangedEventArgs e) { @@ -287,9 +287,10 @@ private async void pivot_SelectionChanged(object sender, SelectionChangedEventAr { await m_userSubmitVideoViewModel.GetSubmitVideo(); } - if (pivot.SelectedIndex == 1 && m_userDynamicViewModel.Items == null) + if (pivot.SelectedIndex == 1 && DynamicSpaceFrame.Content==null) { - await m_userDynamicViewModel.GetDynamicItems(); + DynamicSpaceFrame.Navigate(typeof(DynamicSpacePage), m_viewModel.Mid); + //await m_userDynamicViewModel.GetDynamicItems(); } if (pivot.SelectedIndex == 2 && userSubmitArticleVM.SubmitArticleItems == null) { diff --git a/src/BiliLite.UWP/Pages/WebPage.xaml.cs b/src/BiliLite.UWP/Pages/WebPage.xaml.cs index ec3538fb..a05666ed 100644 --- a/src/BiliLite.UWP/Pages/WebPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/WebPage.xaml.cs @@ -35,7 +35,7 @@ public WebPage() private async void CoreWebView2_NewWindowRequested(CoreWebView2 sender, CoreWebView2NewWindowRequestedEventArgs args) { args.Handled = true; - var handelUrlResult = await MessageCenter.HandelUrl(sender.Source); + var handelUrlResult = await MessageCenter.HandelUrl(args.Uri); if (handelUrlResult) return; var md = new MessageDialog("是否使用外部浏览器打开此链接?"); md.Commands.Add(new UICommand("确定", new UICommandInvokedHandler(async (e) => { await Windows.System.Launcher.LaunchUriAsync(new Uri(args.Uri)); }))); diff --git a/src/BiliLite.UWP/Services/GrpcService.cs b/src/BiliLite.UWP/Services/GrpcService.cs index 68080131..5dcd9ccb 100644 --- a/src/BiliLite.UWP/Services/GrpcService.cs +++ b/src/BiliLite.UWP/Services/GrpcService.cs @@ -63,6 +63,35 @@ public async Task GetDynAll(int page = 1) } } + public async Task GetDynSpace(long mid,string from = "space", int page = 1,string offset = null) + { + var message = new DynSpaceReq() + { + Page = page, + From = from, + HostUid = mid + }; + if (offset != null) + { + message.HistoryOffset = offset; + } + var requestUserInfo = new GrpcBiliUserInfo( + SettingService.Account.AccessKey, + SettingService.Account.UserID, + SettingService.Account.GetLoginAppKeySecret().Appkey); + + var result = await GrpcRequest.Instance.SendMessage("https://grpc.biliapi.net:443/bilibili.app.dynamic.v2.Dynamic/DynSpace", message, requestUserInfo); + if (result.status) + { + var reply = DynSpaceRsp.Parser.ParseFrom(result.results); + return reply; + } + else + { + throw new Exception(result.message); + } + } + public async Task GetDynVideo(int page, string historyOffset, string updateBaseline) { var message = new DynVideoReq() diff --git a/src/BiliLite.UWP/Services/MessageCenter.cs b/src/BiliLite.UWP/Services/MessageCenter.cs index ba2fb431..0d916fd1 100644 --- a/src/BiliLite.UWP/Services/MessageCenter.cs +++ b/src/BiliLite.UWP/Services/MessageCenter.cs @@ -104,6 +104,31 @@ public static async Task HandelUrl(string url, bool dontGoTo = false) { url = await BiliExtensions.GetShortLinkLocation(url); } + + + + /* + * 直播 + * http://live.bilibili.com/live/5619438.html + * http://live.bilibili.com/h5/5619438 + * http://live.bilibili.com/5619438 + * bilibili://live/5619438 + */ + + var live = StringExtensions.RegexMatch(url.Replace("h5", "live").Replace("live.bilibili.com", "live").Replace("/", ""), @"live(\d+)"); + if (live != "") + { + NavigateToPage(null, new NavigationInfo() + { + icon = Symbol.Video, + page = typeof(LiveDetailPage), + title = "直播间加载中...", + parameters = live, + dontGoTo = dontGoTo, + }); + return true; + } + /* * 视频 * https://www.bilibili.com/video/av3905642 @@ -265,28 +290,6 @@ await BiliExtensions.BangumiEpidToSid(bangumi), - /* - * 直播 - * http://live.bilibili.com/live/5619438.html - * http://live.bilibili.com/h5/5619438 - * http://live.bilibili.com/5619438 - * bilibili://live/5619438 - */ - - var live = StringExtensions.RegexMatch(url.Replace("h5", "live").Replace("live.bilibili.com", "live").Replace("/", ""), @"live(\d+)"); - if (live != "") - { - NavigateToPage(null, new NavigationInfo() - { - icon = Symbol.Video, - page = typeof(LiveDetailPage), - title = "直播间加载中...", - parameters = live, - dontGoTo = dontGoTo, - }); - return true; - } - ///* // * 小视频 // * http://vc.bilibili.com/mobile/detail?vc=1399466&bilifrom=1 diff --git a/src/BiliLite.UWP/Startup.cs b/src/BiliLite.UWP/Startup.cs index c24fbe15..811ce56d 100644 --- a/src/BiliLite.UWP/Startup.cs +++ b/src/BiliLite.UWP/Startup.cs @@ -11,6 +11,7 @@ public void ConfigureServices(HostBuilderContext context, IServiceCollection ser { services.AddMapper(); services.AddViewModels(); + services.AddControls(); services.AddDanmakuController(); services.AddSingleton(); diff --git a/src/BiliLite.UWP/Themes/Dark.xaml b/src/BiliLite.UWP/Themes/Dark.xaml index 3438a4ed..9e085fc8 100644 --- a/src/BiliLite.UWP/Themes/Dark.xaml +++ b/src/BiliLite.UWP/Themes/Dark.xaml @@ -14,6 +14,8 @@ #CC000000 #ec407a #008ac5 + Gray + #805C5C5C #FF282828 diff --git a/src/BiliLite.UWP/Themes/Light.xaml b/src/BiliLite.UWP/Themes/Light.xaml index 6d373c7e..1e655668 100644 --- a/src/BiliLite.UWP/Themes/Light.xaml +++ b/src/BiliLite.UWP/Themes/Light.xaml @@ -14,6 +14,8 @@ #CC000000 #ec407a #008ac5 + Gray + #805C5C5C #FFF9F9F9 diff --git a/src/BiliLite.UWP/ViewModels/Comment/CommentControlViewModel.cs b/src/BiliLite.UWP/ViewModels/Comment/CommentControlViewModel.cs index a5a50aa5..c05db6f4 100644 --- a/src/BiliLite.UWP/ViewModels/Comment/CommentControlViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/Comment/CommentControlViewModel.cs @@ -32,9 +32,9 @@ public class CommentControlViewModel : BaseViewModel public double Width { get; set; } = 320; - [DependsOn(nameof(Width))] public bool IsNarrowMode => Width < 300; + [DependsOn(nameof(Width))] public bool IsNarrowMode => Width < 360; - [DependsOn(nameof(Width))] public bool IsWideMode => Width >= 300; + [DependsOn(nameof(Width))] public bool IsWideMode => Width >= 360; [DependsOn(nameof(Width))] public bool IsNarrow2Mode => Width < 200; diff --git a/src/BiliLite.UWP/ViewModels/Comment/CommentViewModel.cs b/src/BiliLite.UWP/ViewModels/Comment/CommentViewModel.cs index 8cbafb2e..1a8e5a6e 100644 --- a/src/BiliLite.UWP/ViewModels/Comment/CommentViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/Comment/CommentViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using Windows.UI; using Windows.UI.Xaml; @@ -151,6 +152,18 @@ public string Time public ObservableCollection Replies { get; set; } + public List HotReplies { get; set; } + + [DependsOn(nameof(ShowReplies))] + public bool ShowHotReplies + { + get + { + if (!SettingService.GetValue(SettingConstants.UI.SHOW_HOT_REPLIES, SettingConstants.UI.DEFAULT_SHOW_HOT_REPLIES)) return false; + return !ShowReplies; + } + } + //public ObservableCollection replies { get; set; } public bool ShowReplies { get; set; } = false; diff --git a/src/BiliLite.UWP/Modules/EmoteVM.cs b/src/BiliLite.UWP/ViewModels/EmoteViewModel.cs similarity index 71% rename from src/BiliLite.UWP/Modules/EmoteVM.cs rename to src/BiliLite.UWP/ViewModels/EmoteViewModel.cs index 01a71c98..0d4beef7 100644 --- a/src/BiliLite.UWP/Modules/EmoteVM.cs +++ b/src/BiliLite.UWP/ViewModels/EmoteViewModel.cs @@ -1,43 +1,34 @@ -using BiliLite.Models; -using BiliLite.Models.Requests.Api; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using BiliLite.Extensions; +using BiliLite.Models; +using BiliLite.Models.Requests.Api; +using BiliLite.ViewModels.Common; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; -namespace BiliLite.Modules +namespace BiliLite.ViewModels { - public class EmoteVM : IModules + public class EmoteViewModel : BaseViewModel { - readonly EmoteApi emoteApi; - public EmoteVM() - { - emoteApi = new EmoteApi(); - } - - private List _packages; + private readonly EmoteApi m_emoteApi; - public List Packages + public EmoteViewModel() { - get { return _packages; } - set { _packages = value; DoPropertyChanged("Packages"); } + m_emoteApi = new EmoteApi(); } - private bool _loading = true; - public bool Loading - { - get { return _loading; } - set { _loading = value; DoPropertyChanged("Loading"); } - } + public List Packages { get; set; } + + public bool Loading { get; set; } = true; public async Task GetEmote(EmoteBusiness business) { try { Loading = true; - var api = emoteApi.UserEmote(business); + var api = m_emoteApi.UserEmote(business); var results = await api.Request(); if (results.status) @@ -60,7 +51,7 @@ public async Task GetEmote(EmoteBusiness business) } catch (Exception ex) { - var handel = HandelError(ex); + var handel = HandelError(ex); Notify.ShowMessageToast(handel.message); } finally @@ -70,7 +61,6 @@ public async Task GetEmote(EmoteBusiness business) } } - public class EmotePackageModel { public int id { get; set; } @@ -81,6 +71,7 @@ public class EmotePackageModel public int attr { get; set; } public List emote { get; set; } } + public class EmotePackageItemModel { public int id { get; set; } diff --git a/src/BiliLite.UWP/Modules/User/SendDynamic/AtVM.cs b/src/BiliLite.UWP/ViewModels/User/SendDynamic/AtViewModel.cs similarity index 78% rename from src/BiliLite.UWP/Modules/User/SendDynamic/AtVM.cs rename to src/BiliLite.UWP/ViewModels/User/SendDynamic/AtViewModel.cs index 5ed9ac29..d88f3015 100644 --- a/src/BiliLite.UWP/Modules/User/SendDynamic/AtVM.cs +++ b/src/BiliLite.UWP/ViewModels/User/SendDynamic/AtViewModel.cs @@ -6,48 +6,50 @@ using System.Threading.Tasks; using System.Windows.Input; using BiliLite.Extensions; +using BiliLite.Models.Common.User.SendDynamic; +using BiliLite.Modules; +using BiliLite.ViewModels.Common; +using PropertyChanged; -namespace BiliLite.Modules.User +namespace BiliLite.ViewModels.User.SendDynamic { - public class AtVM : IModules + public class AtViewModel : BaseViewModel { - readonly AtApi atApi; - public AtVM() + readonly AtApi m_atApi; + + public AtViewModel() { - atApi = new AtApi(); + m_atApi = new AtApi(); SearchCommand = new RelayCommand(Search); LoadMoreCommand = new RelayCommand(LoadMore); Users = new ObservableCollection(); } + + [DoNotNotify] public ICommand LoadMoreCommand { get; private set; } - public ICommand SearchCommand { get; private set; } + [DoNotNotify] + public ICommand SearchCommand { get; private set; } - private ObservableCollection _user; + public ObservableCollection Users { get; set; } - public ObservableCollection Users - { - get { return _user; } - set { _user = value; DoPropertyChanged("Users"); } - } + public bool Loading { get; set; } = true; - private bool _loading = true; - public bool Loading - { - get { return _loading; } - set { _loading = value; DoPropertyChanged("Loading"); } - } + [DoNotNotify] public int Page { get; set; } = 1; + + [DoNotNotify] public string Keyword { get; set; } + public async Task GetUser() { try { Loading = true; - var api = atApi.RecommendAt(Page); + var api = m_atApi.RecommendAt(Page); if (!string.IsNullOrEmpty(Keyword)) { - api = atApi.SearchUser(Keyword, Page); + api = m_atApi.SearchUser(Keyword, Page); } if (Page == 1) { @@ -102,7 +104,7 @@ public async Task GetUser() } catch (Exception ex) { - var handel = HandelError(ex); + var handel = HandelError(ex); Notify.ShowMessageToast(handel.message); } finally @@ -132,11 +134,4 @@ public async void Search(string keyword) await GetUser(); } } -} -public class AtUserModel -{ - public long ID { get; set; } - public string UserName { get; set; } - public string Face { get; set; } - public string Display { get { return "@" + UserName; } } } \ No newline at end of file diff --git a/src/BiliLite.UWP/ViewModels/User/SendDynamic/SendDynamicV2ViewModel.cs b/src/BiliLite.UWP/ViewModels/User/SendDynamic/SendDynamicV2ViewModel.cs new file mode 100644 index 00000000..61c59fd6 --- /dev/null +++ b/src/BiliLite.UWP/ViewModels/User/SendDynamic/SendDynamicV2ViewModel.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading.Tasks; +using Windows.Storage; +using BiliLite.Extensions; +using BiliLite.Models; +using BiliLite.Models.Common; +using BiliLite.Models.Common.User.SendDynamic; +using BiliLite.Models.Exceptions; +using BiliLite.Models.Requests.Api.User; +using BiliLite.Models.Responses; +using BiliLite.Services; +using BiliLite.ViewModels.Common; +using BiliLite.ViewModels.UserDynamic; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PropertyChanged; +using RestSharp; + +namespace BiliLite.ViewModels.User.SendDynamic +{ + public class SendDynamicV2ViewModel : BaseViewModel + { + #region Fields + + private static readonly ILogger _logger = GlobalLogger.FromCurrentType(); + readonly DynamicAPI m_dynamicApi; + private List m_atDisplaylist = new List(); + private List m_atlist = new List(); + + #endregion + + #region Constructors + + public SendDynamicV2ViewModel() + { + m_dynamicApi = new DynamicAPI(); + Images = new ObservableCollection(); + } + + #endregion + + #region Properties + + public bool IsRepost { get; set; } + + public DynamicV2ItemViewModel RepostInfo { get; set; } + + public ObservableCollection Images { get; set; } + + public bool Uploading { get; set; } + + public bool ShowImage { get; set; } + + public string Content { get; set; } = ""; + + [DependsOn(nameof(Content))] + public int Count => Content.Length; + + #endregion + + #region Public Methods + + public void SetRepost(DynamicV2ItemViewModel repostInfo) + { + RepostInfo = repostInfo; + IsRepost = true; + } + + public void AddAtItem(AtDisplayModel atDisplayModel) + { + m_atDisplaylist.Add(atDisplayModel); + } + + public async void UploadImage(StorageFile file) + { + try + { + Uploading = true; + var api = m_dynamicApi.UploadImage(); + + var fileStream = await file.OpenAsync(FileAccessMode.Read); + var bytes = new byte[fileStream.Size]; + await fileStream.ReadAsync(bytes.AsBuffer(), (uint)fileStream.Size, Windows.Storage.Streams.InputStreamOptions.None); + var client = new RestClient(api.url); + var request = new RestRequest(); + request.Method = Method.Post; + request.AddParameter("biz", "draw"); + request.AddParameter("category", "daily"); + request.AddFile("file_up", bytes, file.Name); + var response = await client.ExecuteAsync(request); + var content = response.Content; + + var result = JsonConvert.DeserializeObject>(content); + if (result.code == 0) + { + result.data.ImageSize = (await file.GetBasicPropertiesAsync()).Size / 1024; + Images.Add(result.data); + } + else + { + Notify.ShowMessageToast(result.message); + } + } + catch (Exception ex) + { + _logger.Log("图片上传失败", LogType.Fatal, ex); + Notify.ShowMessageToast("图片上传失败"); + } + finally + { + Uploading = false; + ShowImage = Images.Count > 0; + } + } + + /// + /// 转发 + /// + public async Task SendRepost() + { + var ctrl = "[]"; + var at_uids = ""; + m_atlist.Clear(); + + if (m_atDisplaylist.Count != 0) + { + + foreach (var item in m_atDisplaylist.Where(item => Content.Contains(item.Text))) + { + m_atlist.Add(new AtModel() + { + Data = item.Data.ToString(), + Length = item.Length - 2, + Location = Content.IndexOf(item.Text), + Type = 1 + }); + var d = item.Text.Replace("[", "").Replace("]", ""); + Content = Content.Replace(item.Text, d); + at_uids += item.Data.ToString() + ","; + } + ctrl = JsonConvert.SerializeObject(m_atlist); + at_uids = at_uids.Remove(at_uids.Length - 1, 1); + m_atDisplaylist.Clear(); + } + if (Content == "") + { + Content = "转发动态"; + } + + try + { + var httpResults = await m_dynamicApi.RepostDynamic(RepostInfo.Extend.DynIdStr, Content, at_uids, ctrl) + .Request(); + if (!httpResults.status) + throw new CustomizedErrorException(httpResults.message); + var data = await httpResults.GetData(); + if (data.code != 0) + throw new CustomizedErrorException("发表动态失败:" + data.message); + + Notify.ShowMessageToast("转发成功"); + m_atDisplaylist.Clear(); + return true; + } + catch (CustomizedErrorException ex) + { + Notify.ShowMessageToast(ex.Message); + _logger.Log(ex.Message, LogType.Error, ex); + return false; + } + catch (Exception ex) + { + Notify.ShowMessageToast("转发动态失败" + ex.Message); + _logger.Log("转发动态失败", LogType.Error, ex); + return false; + } + } + + public async Task SendDynamic() + { + if (Content.Trim().Length == 0) + { + Notify.ShowMessageToast("不能发送空白动态"); + return false; + } + + var ctrl = "[]"; + var at_uids = ""; + m_atlist.Clear(); + var txt = Content; + if (m_atDisplaylist.Count != 0) + { + foreach (var item in m_atDisplaylist.Where(item => txt.Contains(item.Text))) + { + m_atlist.Add(new AtModel() + { + Data = item.Data.ToString(), + Length = item.Length - 2, + Location = txt.IndexOf(item.Text), + Type = 1 + }); + var d = item.Text.Replace("[", "").Replace("]", ""); + txt = txt.Replace(item.Text, d); + at_uids += item.Data.ToString() + ","; + } + ctrl = JsonConvert.SerializeObject(m_atlist); + at_uids = at_uids.Remove(at_uids.Length - 1, 1); + + } + + var sendPics = Images.Select(item => new SendImagesModel() { ImgHeight = item.ImageHeight, ImgSize = item.ImageSize, ImgSrc = item.ImageUrl, ImgWidth = item.ImageWidth }).ToList(); + var imgStr = JsonConvert.SerializeObject(sendPics); + try + { + HttpResults httpResults; + if (sendPics.Count == 0) + { + httpResults = await m_dynamicApi.CreateDynamicText(txt, at_uids, ctrl).Request(); + } + else + { + httpResults = await m_dynamicApi.CreateDynamicPhoto(imgStr, txt, at_uids, ctrl).Request(); + } + + if (!httpResults.status) + throw new CustomizedErrorException(httpResults.message); + + var data = await httpResults.GetData(); + if (data.code != 0) + throw new CustomizedErrorException("发表动态失败:" + data.message); + + Notify.ShowMessageToast("发表动态成功"); + m_atDisplaylist.Clear(); + return true; + } + catch (CustomizedErrorException ex) + { + Notify.ShowMessageToast(ex.Message); + _logger.Log(ex.Message, LogType.Error, ex); + return false; + } + catch (Exception ex) + { + Notify.ShowMessageToast("发表动态发生错误"); + _logger.Log("发表动态失败", LogType.Error, ex); + return false; + } + + } + + #endregion + } +} diff --git a/src/BiliLite.UWP/ViewModels/User/SendDynamic/SendDynamicViewModel.cs b/src/BiliLite.UWP/ViewModels/User/SendDynamic/SendDynamicViewModel.cs new file mode 100644 index 00000000..502598ae --- /dev/null +++ b/src/BiliLite.UWP/ViewModels/User/SendDynamic/SendDynamicViewModel.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading.Tasks; +using Windows.Storage; +using BiliLite.Extensions; +using BiliLite.Models; +using BiliLite.Models.Common; +using BiliLite.Models.Common.User.SendDynamic; +using BiliLite.Models.Exceptions; +using BiliLite.Models.Requests.Api.User; +using BiliLite.Models.Responses; +using BiliLite.Services; +using BiliLite.ViewModels.Common; +using BiliLite.ViewModels.UserDynamic; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PropertyChanged; +using RestSharp; + +namespace BiliLite.ViewModels.User.SendDynamic +{ + public class SendDynamicViewModel : BaseViewModel + { + #region Fields + + private static readonly ILogger _logger = GlobalLogger.FromCurrentType(); + readonly DynamicAPI m_dynamicApi; + private List m_atDisplaylist = new List(); + private List m_atlist = new List(); + + #endregion + + #region Constructors + + public SendDynamicViewModel() + { + m_dynamicApi = new DynamicAPI(); + Images = new ObservableCollection(); + } + + #endregion + + #region Properties + + public bool IsRepost { get; set; } + + public UserDynamicItemDisplayViewModel RepostInfo { get; set; } + + public ObservableCollection Images { get; set; } + + public bool Uploading { get; set; } + + public bool ShowImage { get; set; } + + public string Content { get; set; } = ""; + + [DependsOn(nameof(Content))] + public int Count => Content.Length; + + #endregion + + #region Public Methods + + public void SetRepost(UserDynamicItemDisplayViewModel repostInfo) + { + RepostInfo = repostInfo; + IsRepost = true; + } + + public void AddAtItem(AtDisplayModel atDisplayModel) + { + m_atDisplaylist.Add(atDisplayModel); + } + + public async void UploadImage(StorageFile file) + { + try + { + Uploading = true; + var api = m_dynamicApi.UploadImage(); + + var fileStream = await file.OpenAsync(FileAccessMode.Read); + var bytes = new byte[fileStream.Size]; + await fileStream.ReadAsync(bytes.AsBuffer(), (uint)fileStream.Size, Windows.Storage.Streams.InputStreamOptions.None); + var client = new RestClient(api.url); + var request = new RestRequest(); + request.Method = Method.Post; + request.AddParameter("biz", "draw"); + request.AddParameter("category", "daily"); + request.AddFile("file_up", bytes, file.Name); + var response = await client.ExecuteAsync(request); + var content = response.Content; + + var result = JsonConvert.DeserializeObject>(content); + if (result.code == 0) + { + result.data.ImageSize = (await file.GetBasicPropertiesAsync()).Size / 1024; + Images.Add(result.data); + } + else + { + Notify.ShowMessageToast(result.message); + } + } + catch (Exception ex) + { + _logger.Log("图片上传失败", LogType.Fatal, ex); + Notify.ShowMessageToast("图片上传失败"); + } + finally + { + Uploading = false; + ShowImage = Images.Count > 0; + } + } + + /// + /// 转发 + /// + public async Task SendRepost() + { + var ctrl = "[]"; + var at_uids = ""; + m_atlist.Clear(); + + if (m_atDisplaylist.Count != 0) + { + + foreach (var item in m_atDisplaylist.Where(item => Content.Contains(item.Text))) + { + m_atlist.Add(new AtModel() + { + Data = item.Data.ToString(), + Length = item.Length - 2, + Location = Content.IndexOf(item.Text), + Type = 1 + }); + var d = item.Text.Replace("[", "").Replace("]", ""); + Content = Content.Replace(item.Text, d); + at_uids += item.Data.ToString() + ","; + } + ctrl = JsonConvert.SerializeObject(m_atlist); + at_uids = at_uids.Remove(at_uids.Length - 1, 1); + m_atDisplaylist.Clear(); + } + if (Content == "") + { + Content = "转发动态"; + } + + try + { + var httpResults = await m_dynamicApi.RepostDynamic(RepostInfo.DynamicID, Content, at_uids, ctrl) + .Request(); + if (!httpResults.status) + throw new CustomizedErrorException(httpResults.message); + var data = await httpResults.GetData(); + if (data.code != 0) + throw new CustomizedErrorException("发表动态失败:" + data.message); + + Notify.ShowMessageToast("转发成功"); + m_atDisplaylist.Clear(); + return true; + } + catch (CustomizedErrorException ex) + { + Notify.ShowMessageToast(ex.Message); + _logger.Log(ex.Message, LogType.Error, ex); + return false; + } + catch (Exception ex) + { + Notify.ShowMessageToast("转发动态失败" + ex.Message); + _logger.Log("转发动态失败", LogType.Error, ex); + return false; + } + } + + public async Task SendDynamic() + { + if (Content.Trim().Length == 0) + { + Notify.ShowMessageToast("不能发送空白动态"); + return false; + } + + var ctrl = "[]"; + var at_uids = ""; + m_atlist.Clear(); + var txt = Content; + if (m_atDisplaylist.Count != 0) + { + foreach (var item in m_atDisplaylist.Where(item => txt.Contains(item.Text))) + { + m_atlist.Add(new AtModel() + { + Data = item.Data.ToString(), + Length = item.Length - 2, + Location = txt.IndexOf(item.Text), + Type = 1 + }); + var d = item.Text.Replace("[", "").Replace("]", ""); + txt = txt.Replace(item.Text, d); + at_uids += item.Data.ToString() + ","; + } + ctrl = JsonConvert.SerializeObject(m_atlist); + at_uids = at_uids.Remove(at_uids.Length - 1, 1); + + } + + var sendPics = Images.Select(item => new SendImagesModel() { ImgHeight = item.ImageHeight, ImgSize = item.ImageSize, ImgSrc = item.ImageUrl, ImgWidth = item.ImageWidth }).ToList(); + var imgStr = JsonConvert.SerializeObject(sendPics); + try + { + HttpResults httpResults; + if (sendPics.Count == 0) + { + httpResults = await m_dynamicApi.CreateDynamicText(txt, at_uids, ctrl).Request(); + } + else + { + httpResults = await m_dynamicApi.CreateDynamicPhoto(imgStr, txt, at_uids, ctrl).Request(); + } + + if (!httpResults.status) + throw new CustomizedErrorException(httpResults.message); + + var data = await httpResults.GetData(); + if (data.code != 0) + throw new CustomizedErrorException("发表动态失败:" + data.message); + + Notify.ShowMessageToast("发表动态成功"); + m_atDisplaylist.Clear(); + return true; + } + catch (CustomizedErrorException ex) + { + Notify.ShowMessageToast(ex.Message); + _logger.Log(ex.Message, LogType.Error, ex); + return false; + } + catch (Exception ex) + { + Notify.ShowMessageToast("发表动态发生错误"); + _logger.Log("发表动态失败", LogType.Error, ex); + return false; + } + + } + + #endregion + } +} diff --git a/src/BiliLite.UWP/Modules/User/SendDynamic/TopicVM.cs b/src/BiliLite.UWP/ViewModels/User/SendDynamic/TopicViewModel.cs similarity index 61% rename from src/BiliLite.UWP/Modules/User/SendDynamic/TopicVM.cs rename to src/BiliLite.UWP/ViewModels/User/SendDynamic/TopicViewModel.cs index 38a51934..e1f76444 100644 --- a/src/BiliLite.UWP/Modules/User/SendDynamic/TopicVM.cs +++ b/src/BiliLite.UWP/ViewModels/User/SendDynamic/TopicViewModel.cs @@ -1,37 +1,29 @@ -using BiliLite.Models; -using BiliLite.Models.Requests.Api.User; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; +using System; using System.Collections.ObjectModel; using System.Threading.Tasks; using BiliLite.Extensions; +using BiliLite.Models; +using BiliLite.Models.Common.User.SendDynamic; +using BiliLite.Models.Requests.Api.User; +using BiliLite.ViewModels.Common; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; -namespace BiliLite.Modules.User.SendDynamic +namespace BiliLite.ViewModels.User.SendDynamic { - public class TopicVM : IModules + public class TopicViewModel : BaseViewModel { readonly DynamicAPI dynamicAPI; - public TopicVM() + + public TopicViewModel() { dynamicAPI = new DynamicAPI(); Items = new ObservableCollection(); } - private ObservableCollection _items; - - public ObservableCollection Items - { - get { return _items; } - set { _items = value; DoPropertyChanged("Items"); } - } + public ObservableCollection Items { get; set; } - private bool _loading = true; - public bool Loading - { - get { return _loading; } - set { _loading = value; DoPropertyChanged("Loading"); } - } + public bool Loading { get; set; } = true; public async Task GetTopic() { @@ -62,7 +54,7 @@ public async Task GetTopic() } catch (Exception ex) { - var handel = HandelError(ex); + var handel = HandelError(ex); Notify.ShowMessageToast(handel.message); } finally @@ -70,19 +62,5 @@ public async Task GetTopic() Loading = false; } } - - - } - - public class RcmdTopicModel - { - public int topic_id { get; set; } - public string topic_name { get; set; } - public int is_activity { get; set; } - public string display - { - get { return "#" + topic_name + "#"; } - } - } } diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs new file mode 100644 index 00000000..219633d3 --- /dev/null +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Windows.UI.Xaml.Controls; +using AutoMapper; +using Bilibili.App.Dynamic.V2; +using BiliLite.Extensions; +using BiliLite.Models.Common; +using BiliLite.Models.Common.UserDynamic; +using BiliLite.ViewModels.Common; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using PropertyChanged; + +namespace BiliLite.ViewModels.UserDynamic +{ + public class DynamicV2ItemViewModel:BaseViewModel + { + private ModuleDynamic m_dynamic; + private ModuleStat m_stat; + private readonly IMapper m_mapper; + + public DynamicV2ItemViewModel() + { + m_mapper = App.ServiceProvider.GetRequiredService(); + } + + public UserDynamicSpaceViewModel Parent { get; set; } + + public string CardType { get; set; } + + public string ItemType { get; set; } + + public ModuleAuthor Author { get; set; } + + public ModuleAuthorForward AuthorForward { get; set; } + + public ModuleDynamic Dynamic + { + get + { + return m_dynamic; + } + set + { + m_dynamic = value; + if (value.DynForward != null) + { + Item = m_mapper.Map(value.DynForward.Item); + } + + if (value.DynLiveRcmd != null) + { + LiveInfo = JsonConvert.DeserializeObject(value.DynLiveRcmd.Content); + } + } + } + + public DynLiveInfo LiveInfo { get; set; } + + public ModuleDesc Desc { get; set; } + + public DynamicV2ItemViewModel Item { get; set; } + + public List Items + { + get + { + Item.Parent = Parent; + return new List() + { + Item + }; + } + } + + public ModuleStat Stat + { + get => m_stat; + set + { + m_stat = value; + Liked = value.LikeInfo.IsLike; + LikeCount = value.Like; + } + } + + public bool Liked { get; set; } + + public long LikeCount { get; set; } + + public Extend Extend { get; set; } + + [DependsOn(nameof(Content))] + public bool ShowContent => Desc != null; + + [DependsOn(nameof(Desc))] + public RichTextBlock Content + { + get + { + try + { + if (Desc != null) + { + return + Desc.Text.UserDynamicStringToRichText( + Extend.DynIdStr, wordNodes: Extend.OpusSummary?.Summary?.Text?.Nodes?.ToList(), + bindingCommands: nameof(Parent)); + } + + return new RichTextBlock(); + } + catch (Exception ex) + { + return new RichTextBlock(); + } + } + } + + public int CoverWidth => 160; + + [DependsOn(nameof(AuthorForward),nameof(CardType),nameof(ItemType))] + public bool IsRepost => AuthorForward != null; + + public List ImageInfos + { + get + { + var drawItems = this.Dynamic.DynDraw.Items; + var allImages = drawItems.Select(x => x.Src).ToList(); + + return drawItems.Select((t, i) => new UserDynamicItemDisplayImageInfo() + { + AllImages = allImages, + Height = t.Height, + ImageUrl = t.Src, + Width = t.Width, + Index = i, + ImageCommand = Parent.ImageCommand, + }) + .ToList(); + } + } + + [DoNotNotify] + public string Verify { get; set; } = Constants.App.TRANSPARENT_IMAGE; + + [DoNotNotify] + public string Pendant { get; set; } = Constants.App.TRANSPARENT_IMAGE; + } +} \ No newline at end of file diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs new file mode 100644 index 00000000..73396fd4 --- /dev/null +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Input; +using Windows.UI.Xaml.Controls; +using AutoMapper; +using Bilibili.App.Dynamic.V2; +using BiliLite.Extensions; +using BiliLite.Models.Common; +using BiliLite.Models.Exceptions; +using BiliLite.Modules; +using BiliLite.Pages; +using BiliLite.Services; +using BiliLite.ViewModels.Common; +using BiliLite.Models.Common.UserDynamic; +using BiliLite.Pages.User; +using BiliLite.Models; +using BiliLite.Models.Requests.Api.User; +using BiliLite.Dialogs; +using BiliLite.Modules.User; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; + +namespace BiliLite.ViewModels.UserDynamic +{ + public class UserDynamicSpaceViewModel : BaseViewModel + { + #region Fields + + private static readonly ILogger _logger = GlobalLogger.FromCurrentType(); + private readonly GrpcService m_grpcService; + private readonly IMapper m_mapper; + private readonly DynamicAPI m_dynamicApi; + private readonly WatchLaterVM m_watchLaterVm; + private int m_page = 1; + private string m_offset = null; + + #endregion + + #region Constructors + + public UserDynamicSpaceViewModel(GrpcService grpcService, IMapper mapper) + { + m_grpcService = grpcService; + m_mapper = mapper; + m_dynamicApi = new DynamicAPI(); + m_watchLaterVm = new WatchLaterVM(); + LoadMoreCommand = new RelayCommand(LoadMore); + UserCommand = new RelayCommand(OpenUser); + DetailCommand = new RelayCommand(OpenDetail); + ImageCommand = new RelayCommand(OpenImage); + WebDetailCommand = new RelayCommand(OpenWebDetail); + CommentCommand = new RelayCommand(OpenComment); + LikeCommand = new RelayCommand(DoLike); + RepostCommand = new RelayCommand(OpenSendDynamicDialog); + LaunchUrlCommand = new RelayCommand(LaunchUrl); + CopyDynCommand = new RelayCommand(CopyDyn); + TagCommand = new RelayCommand(OpenTag); + WatchLaterCommand = m_watchLaterVm.AddCommandWithAvId; + } + + #endregion + + #region Properties + + public ICommand LaunchUrlCommand { get; set; } + + public ICommand RepostCommand { get; set; } + + public ICommand LikeCommand { get; set; } + + public ICommand CommentCommand { get; set; } + + public ICommand UserCommand { get; set; } + + public ICommand LoadMoreCommand { get; private set; } + + public ICommand WebDetailCommand { get; set; } + + public ICommand DetailCommand { get; set; } + + public ICommand ImageCommand { get; set; } + + public ICommand WatchLaterCommand { get; set; } + + public ICommand CopyDynCommand { get; set; } + + public ICommand TagCommand { get; set; } + + public bool CanLoadMore { get; set; } + + public bool Loading { get; set; } + + public string UserId { get; set; } + + public ObservableCollection DynamicItems { get; set; } + + public int CommentControlWidth + { + get + { + return SettingService.GetValue(SettingConstants.UI.RIGHT_DETAIL_WIDTH, 320); + } + } + + #endregion + + #region Events + + public event EventHandler OpenCommentEvent; + + #endregion + + #region Private Methods + + private void OpenUser(object userId) + { + MessageCenter.NavigateToPage(this, new NavigationInfo() + { + icon = Symbol.Contact, + page = typeof(UserInfoPage), + title = "用户中心", + parameters = userId + }); + } + + private void OpenComment(DynamicV2ItemViewModel data) + { + OpenCommentEvent?.Invoke(this, data); + } + + private void OpenWebDetail(string dynId) + { + var url = $"https://www.bilibili.com/opus/{dynId}"; + MessageCenter.NavigateToPage(null, new NavigationInfo() + { + icon = Symbol.World, + page = typeof(WebPage), + title = "加载中...", + parameters = url + }); + } + + private void OpenTag(object name) + { + //TODO 打开话题 + MessageCenter.NavigateToPage(this, new NavigationInfo() + { + icon = Symbol.World, + page = typeof(WebPage), + title = name.ToString(), + parameters = "https://t.bilibili.com/topic/name/" + Uri.EscapeDataString(name.ToString()) + }); + } + + private void OpenImage(object data) + { + if (!(data is UserDynamicItemDisplayImageInfo imageInfo)) + { + return; + } + MessageCenter.OpenImageViewer(imageInfo.AllImages, imageInfo.Index); + } + + private void OpenDetail(string dynId) + { + MessageCenter.NavigateToPage(this, new NavigationInfo() + { + icon = Symbol.Document, + page = typeof(DynamicDetailPage), + title = "动态详情", + parameters = dynId + }); + } + + private void HandleDynamicResults(DynSpaceRsp results) + { + CanLoadMore = results.HasMore; + m_offset = results.HistoryOffset; + var items = m_mapper.Map>(results.List.ToList()); + foreach (var item in items) + { + item.Parent = this; + } + if (m_page == 1) + DynamicItems = new ObservableCollection(items); + else + { + DynamicItems.AddRange(items); + } + } + + private async void LaunchUrl(string url) + { + var result = await MessageCenter.HandelUrl(url); + if (!result) + { + Notify.ShowMessageToast("无法打开Url"); + } + } + + private async Task DoLikeCore(DynamicV2ItemViewModel item) + { + var results = await m_dynamicApi.Like(item.Extend.DynIdStr, item.Liked ? 2 : 1).Request(); + if (!results.status) + { + throw new CustomizedErrorException(results.message); + } + + var data = await results.GetJson>(); + if (!data.success) + { + throw new CustomizedErrorException(data.message); + } + + if (item.Liked) + { + item.Liked = false; + item.LikeCount -= 1; + } + else + { + item.Liked = true; + item.LikeCount += 1; + } + } + + private async void DoLike(DynamicV2ItemViewModel item) + { + if (!await BiliExtensions.ActionCheckLogin()) return; + + try + { + await DoLikeCore(item); + } + catch (CustomizedErrorException ex) + { + Notify.ShowMessageToast(ex.Message); + _logger.Error(ex.Message); + } + catch (Exception ex) + { + var handel = HandelError(ex); + Notify.ShowMessageToast(handel.message); + } + } + + private async void OpenSendDynamicDialog(DynamicV2ItemViewModel data) + { + if (!await BiliExtensions.ActionCheckLogin()) return; + + var sendDynamicDialog = App.ServiceProvider.GetRequiredService(); + if (data != null) + { + sendDynamicDialog.SetRepost(data); + } + await sendDynamicDialog.ShowAsync(); + } + + private void CopyDyn(DynamicV2ItemViewModel data) + { + var dataStr = JsonConvert.SerializeObject(data); + Notify.ShowMessageToast(dataStr.SetClipboard() ? "已复制" : "复制失败"); + } + + #endregion + + #region Public Methods + + public async void LoadMore() + { + if (Loading) + { + return; + } + if (DynamicItems == null || DynamicItems.Count == 0) + { + return; + } + + await GetDynamicItems(m_page + 1); + } + + public async Task GetDynamicItems(int page = 1) + { + try + { + CanLoadMore = false; + Loading = true; + m_page = page; + if (page == 1) + { + m_offset = null; + } + var results = await m_grpcService.GetDynSpace(UserId.ToInt64(), page: page, offset: m_offset); + HandleDynamicResults(results); + } + catch (CustomizedErrorException ex) + { + Notify.ShowMessageToast(ex.Message); + _logger.Error(ex.Message); + } + catch (Exception ex) + { + var handel = HandelError(ex); + Notify.ShowMessageToast(handel.message); + } + finally + { + Loading = false; + } + } + + #endregion + } +} diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicViewModel.cs index 60ab54e3..ad2c7974 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicViewModel.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Threading.Tasks; using System.Windows.Input; -using Windows.Foundation; using Windows.UI.Popups; using Windows.UI.Xaml.Controls; using AutoMapper; @@ -331,10 +330,10 @@ private async void OpenSendDynamicDialog(UserDynamicItemDisplayViewModel data) { if (!await BiliExtensions.ActionCheckLogin()) return; - var sendDynamicDialog = new SendDynamicDialog(); + var sendDynamicDialog = App.ServiceProvider.GetRequiredService(); if (data != null) { - sendDynamicDialog = new SendDynamicDialog(data); + sendDynamicDialog.SetRepost(data); } await sendDynamicDialog.ShowAsync(); }