From 27cfc3af43719e5b42f0079bfaf5596dfd6dfb2a Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Fri, 12 Apr 2024 20:15:25 +0800 Subject: [PATCH 01/30] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E8=AE=BE=E7=BD=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/BiliLite.UWP.csproj | 6 + .../SettingDefaultValueAttribute.cs | 8 + .../Models/Attributes/SettingKeyAttribute.cs | 19 ++ .../Models/Common/SettingConstants.cs | 134 +++++++++- src/BiliLite.UWP/Pages/SettingPage.xaml | 5 + src/BiliLite.UWP/Pages/SettingPage.xaml.cs | 29 +++ src/BiliLite.UWP/Services/SettingService.cs | 5 + .../Services/SettingsImportExportService.cs | 237 ++++++++++++++++++ src/BiliLite.UWP/Services/WbiKeyService.cs | 2 +- src/BiliLite.UWP/Startup.cs | 1 + 10 files changed, 442 insertions(+), 4 deletions(-) create mode 100644 src/BiliLite.UWP/Models/Attributes/SettingDefaultValueAttribute.cs create mode 100644 src/BiliLite.UWP/Models/Attributes/SettingKeyAttribute.cs create mode 100644 src/BiliLite.UWP/Services/SettingsImportExportService.cs diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj index 0e940315..da65e985 100644 --- a/src/BiliLite.UWP/BiliLite.UWP.csproj +++ b/src/BiliLite.UWP/BiliLite.UWP.csproj @@ -151,6 +151,8 @@ + + @@ -161,6 +163,7 @@ + @@ -1325,6 +1328,9 @@ 1.0.7 + + 0.17.0 + 0.16.8 diff --git a/src/BiliLite.UWP/Models/Attributes/SettingDefaultValueAttribute.cs b/src/BiliLite.UWP/Models/Attributes/SettingDefaultValueAttribute.cs new file mode 100644 index 00000000..3e8746b4 --- /dev/null +++ b/src/BiliLite.UWP/Models/Attributes/SettingDefaultValueAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace BiliLite.Models.Attributes +{ + public class SettingDefaultValueAttribute : Attribute + { + } +} diff --git a/src/BiliLite.UWP/Models/Attributes/SettingKeyAttribute.cs b/src/BiliLite.UWP/Models/Attributes/SettingKeyAttribute.cs new file mode 100644 index 00000000..6cdd8913 --- /dev/null +++ b/src/BiliLite.UWP/Models/Attributes/SettingKeyAttribute.cs @@ -0,0 +1,19 @@ +using System; + +namespace BiliLite.Models.Attributes +{ + public class SettingKeyAttribute:Attribute + { + public SettingKeyAttribute() + { + Type = typeof(string); + } + + public SettingKeyAttribute(Type type) + { + Type = type; + } + + public Type Type { get; set; } + } +} diff --git a/src/BiliLite.UWP/Models/Common/SettingConstants.cs b/src/BiliLite.UWP/Models/Common/SettingConstants.cs index 84ac4dec..bff7547e 100644 --- a/src/BiliLite.UWP/Models/Common/SettingConstants.cs +++ b/src/BiliLite.UWP/Models/Common/SettingConstants.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using BiliLite.Models.Attributes; using BiliLite.Services; namespace BiliLite.Models.Common @@ -10,75 +11,92 @@ public class UI /// /// 加载原图 /// + [SettingKey(typeof(bool))] public const string ORTGINAL_IMAGE = "originalImage"; /// /// 主题颜色 /// + [SettingKey(typeof(int))] public const string THEME_COLOR = "themeColor"; /// /// 主题,0为默认,1为浅色,2为深色 /// + [SettingKey(typeof(int))] public const string THEME = "theme"; /// /// 显示模式,0为多标签,1为单窗口,2为多窗口 /// + [SettingKey(typeof(int))] public const string DISPLAY_MODE = "displayMode"; /// /// 缓存首页 /// + [SettingKey(typeof(bool))] public const string CACHE_HOME = "cacheHome"; /// /// 首页排序 /// + [SettingKey(typeof(object))] public const string HOEM_ORDER = "homePageOrder"; /// /// 右侧详情宽度 /// + [SettingKey(typeof(double))] public const string RIGHT_DETAIL_WIDTH = "PlayerRightDetailWidth"; /// /// 右侧详情宽度可调整 /// + [SettingKey(typeof(bool))] public const string RIGHT_WIDTH_CHANGEABLE = "PlayerRightDetailWidthChangeable"; /// /// 图片圆角半径 /// + [SettingKey(typeof(double))] public const string IMAGE_CORNER_RADIUS = "ImageCornerRadius"; /// /// 视频详情显示封面 /// + [SettingKey(typeof(bool))] public const string SHOW_DETAIL_COVER = "showDetailCover"; + /// /// 新窗口打开图片预览 /// + [SettingKey(typeof(bool))] public const string NEW_WINDOW_PREVIEW_IMAGE = "newWindowPreviewImage"; /// /// 动态显示样式 /// + [SettingKey(typeof(int))] public const string DYNAMIC_DISPLAY_MODE = "dynamicDiaplayMode"; /// /// 首页推荐样式 /// + [SettingKey(typeof(int))] public const string RECMEND_DISPLAY_MODE = "recomendDiaplayMode"; /// /// 右侧选项卡 /// + [SettingKey(typeof(int))] public const string DETAIL_DISPLAY = "detailDisplay"; /// /// 动态显示样式 /// + [SettingKey] public const string BACKGROUND_IMAGE = "BackgroundImage"; /// /// 鼠标功能键行为 /// + [SettingKey(typeof(int))] public const string MOUSE_MIDDLE_ACTION = "MouseMiddleAction"; /// /// 隐藏赞助按钮 @@ -87,35 +105,42 @@ public class UI /// /// 隐藏广告按钮 /// + [SettingKey(typeof(bool))] public const string HIDE_AD = "HideAD"; /// /// 浏览器打开无法处理的链接 /// + [SettingKey(typeof(bool))] public const string OPEN_URL_BROWSER = "OpenUrlWithBrowser"; /// /// 启用长评论折叠 /// + [SettingKey(typeof(bool))] public const string ENABLE_COMMENT_SHRINK = "EnableCommentShrink"; /// /// 折叠评论长度 /// + [SettingKey(typeof(int))] public const string COMMENT_SHRINK_LENGTH = "CommentShrinkLength"; /// /// 默认折叠评论长度 /// + [SettingDefaultValue] public const int COMMENT_SHRINK_DEFAULT_LENGTH = 75; /// /// 显示评论热门回复 /// + [SettingKey(typeof(bool))] public const string SHOW_HOT_REPLIES = "ShowHotReplies"; /// /// 显示评论热门回复默认选项 /// + [SettingDefaultValue] public const bool DEFAULT_SHOW_HOT_REPLIES = true; } @@ -124,62 +149,75 @@ public class Account /// /// 登录后ACCESS_KEY /// + [SettingKey] public const string ACCESS_KEY = "accesskey"; /// /// 登录后REFRESH_KEY /// + [SettingKey] public const string REFRESH_KEY = "refreshkey"; /// /// 到期时间 /// + [SettingKey(typeof(object))] public const string ACCESS_KEY_EXPIRE_DATE = "expireDate"; /// /// 用户ID /// + [SettingKey(typeof(long))] public const string USER_ID = "uid"; /// /// 到期时间 /// + [SettingKey(typeof(object))] public const string USER_PROFILE = "userProfile"; /// /// 是否web登录 /// + [SettingKey(typeof(bool))] public const string IS_WEB_LOGIN = "isWebLogin"; /// /// Cookies /// + [SettingKey] public const string BILIBILI_COOKIES = "BiliBiliCookies"; /// /// 登录用AppKey /// + [SettingKey] public const string LOGIN_APP_KEY_SECRET = "LoginAppKeySecret"; /// /// 默认登录用AppKey /// + [SettingDefaultValue] public static ApiKeyInfo DefaultLoginAppKeySecret = ApiHelper.AndroidKey; /// /// Wbi令牌ImgKey参数 /// + [SettingKey] public const string WBI_IMG_KEY = "WbiImgKey"; /// /// Wbi令牌SubKey参数 /// + [SettingKey] public const string WBI_SUB_KEY = "WbiSubKey"; /// /// Wbi令牌参数获取时间(unix时间戳) /// + [SettingKey(typeof(long))] public const string WBI_KEY_TIME = "WbiKeyTime"; /// /// Wbi令牌参数刷新时间(单位分钟,暂定2小时) /// + [SettingDefaultValue] public const int WBI_KEY_REFRESH_TIME = 120; } @@ -188,90 +226,111 @@ public class VideoDanmaku /// /// 默认弹幕引擎 /// + [SettingDefaultValue] public const DanmakuEngineType DEFAULT_DANMAKU_ENGINE = DanmakuEngineType.NSDanmaku; /// /// 弹幕引擎 /// + [SettingKey(typeof(int))] public const string DANMAKU_ENGINE = "DanmakuEngine"; /// /// 显示弹幕 Visibility /// + [SettingKey(typeof(object))] public const string SHOW = "VideoDanmuShow"; /// /// 弹幕缩放 double /// + [SettingKey(typeof(double))] public const string FONT_ZOOM = "VideoDanmuFontZoom"; /// /// 弹幕显示区域 /// + [SettingKey(typeof(double))] public const string AREA = "VideoDanmuArea"; /// /// 弹幕速度 int /// + [SettingKey(typeof(int))] public const string SPEED = "VideoDanmuSpeed"; /// /// 弹幕加粗 bool /// + [SettingKey(typeof(bool))] public const string BOLD = "VideoDanmuBold"; /// /// 弹幕边框样式 int /// + [SettingKey(typeof(int))] public const string BORDER_STYLE = "VideoDanmuStyle"; /// /// 弹幕合并 bool /// + [SettingKey(typeof(bool))] public const string MERGE = "VideoDanmuMerge"; /// /// 弹幕半屏显示 bool /// + [SettingKey(typeof(bool))] public const string DOTNET_HIDE_SUBTITLE = "VideoDanmuDotHide"; /// /// 弹幕透明度 double,0-1 /// + [SettingKey(typeof(double))] public const string OPACITY = "VideoDanmuOpacity"; /// /// 隐藏顶部 bool /// + [SettingKey(typeof(bool))] public const string HIDE_TOP = "VideoDanmuHideTop"; /// /// 隐藏底部 bool /// + [SettingKey(typeof(bool))] public const string HIDE_BOTTOM = "VideoDanmuHideBottom"; /// /// 隐藏滚动 bool /// + [SettingKey(typeof(bool))] public const string HIDE_ROLL = "VideoDanmuHideRoll"; /// /// 隐藏高级弹幕 bool /// + [SettingKey(typeof(bool))] public const string HIDE_ADVANCED = "VideoDanmuHideAdvanced"; /// /// 关键词屏蔽 ObservableCollection /// + [SettingKey(typeof(object))] public const string SHIELD_WORD = "VideoDanmuShieldWord"; /// /// 用户屏蔽 ObservableCollection /// + [SettingKey(typeof(object))] public const string SHIELD_USER = "VideoDanmuShieldUser"; /// /// 正则屏蔽 ObservableCollection /// + [SettingKey(typeof(object))] public const string SHIELD_REGULAR = "VideoDanmuShieldRegular"; /// /// 顶部距离 /// + [SettingKey(typeof(double))] public const string TOP_MARGIN = "VideoDanmuTopMargin"; /// /// 最大数量 /// + [SettingKey(typeof(double))] public const string MAX_NUM = "VideoDanmuMaxNum"; /// /// 弹幕云屏蔽等级 /// + [SettingKey(typeof(int))] public const string SHIELD_LEVEL = "VideoDanmuShieldLevel"; } @@ -280,49 +339,62 @@ public class Live /// /// 直播默认清晰度 /// + [SettingKey(typeof(int))] public const string DEFAULT_QUALITY = "LiveDefaultQuality"; /// /// 显示弹幕 Visibility /// + [SettingKey(typeof(object))] public const string SHOW = "LiveDanmuShow"; + + [SettingKey(typeof(double))] public const string AREA = "LiveDanmuArea"; /// /// 弹幕缩放 double /// + [SettingKey(typeof(double))] public const string FONT_ZOOM = "LiveDanmuFontZoom"; /// /// 弹幕速度 int /// + [SettingKey(typeof(int))] public const string SPEED = "LiveDanmuSpeed"; /// /// 弹幕加粗 bool /// + [SettingKey(typeof(bool))] public const string BOLD = "LiveDanmuBold"; /// /// 弹幕边框样式 int /// + [SettingKey(typeof(int))] public const string BORDER_STYLE = "LiveDanmuStyle"; /// /// 弹幕半屏显示 bool /// + [SettingKey(typeof(bool))] public const string DOTNET_HIDE_SUBTITLE = "LiveDanmuDotHide"; /// /// 弹幕透明度 double,0-1 /// + [SettingKey(typeof(double))] public const string OPACITY = "LiveDanmuOpacity"; /// /// 关键词屏蔽 ObservableCollection /// + [SettingKey(typeof(object))] public const string SHIELD_WORD = "LiveDanmuShieldWord"; /// /// 硬解 bool /// + [SettingKey(typeof(bool))] public const string HARDWARE_DECODING = "LiveHardwareDecoding"; /// /// 自动开启宝箱 bool /// + [SettingKey(typeof(bool))] public const string AUTO_OPEN_BOX = "LiveAutoOpenBox"; /// @@ -333,16 +405,19 @@ public class Live /// /// 直播弹幕清理 /// + [SettingKey(typeof(int))] public const string DANMU_CLEAN_COUNT = "LiveCleanCount"; /// /// 隐藏进场 /// + [SettingKey(typeof(bool))] public const string HIDE_WELCOME = "LiveHideWelcome"; /// /// 隐藏礼物 /// + [SettingKey(typeof(bool))] public const string HIDE_GIFT = "LiveHideGift"; /// @@ -352,11 +427,13 @@ public class Live /// /// 隐藏抽奖 /// + [SettingKey(typeof(bool))] public const string HIDE_LOTTERY = "LiveHideLottery"; /// /// 直播流默认源 /// + [SettingKey(typeof(string))] public const string DEFAULT_LIVE_PLAY_URL_SOURCE = "DefaultLivePlayUrlSource"; } @@ -365,75 +442,93 @@ public class Player /// /// 使用外站视频替换无法播放的视频 bool /// + [SettingKey(typeof(bool))] public const string USE_OTHER_SITEVIDEO = "PlayerUseOther"; /// /// 硬解 bool /// + [SettingKey(typeof(bool))] public const string HARDWARE_DECODING = "PlayerHardwareDecoding"; /// /// 自动播放 bool /// + [SettingKey(typeof(bool))] public const string AUTO_PLAY = "PlayerAutoPlay"; /// /// 自动切换下一个视频 /// + [SettingKey(typeof(bool))] public const string AUTO_NEXT = "PlayerAutoNext"; /// /// 默认清晰度 int /// + [SettingKey(typeof(int))] public const string DEFAULT_QUALITY = "PlayerDefaultQuality"; /// /// 默认音质 int /// + [SettingKey(typeof(int))] public const string DEFAULT_SOUND_QUALITY = "PlayerDefaultSoundQuality"; /// /// 比例 int /// + [SettingKey(typeof(int))] public const string RATIO = "PlayerDefaultRatio"; /// /// 默认视频类型 int flv=0, dash=1,dash_hevc=2 /// + [SettingKey(typeof(int))] public const string DEFAULT_VIDEO_TYPE = "PlayerDefaultVideoType"; + + [SettingDefaultValue] public static List VideoSpeed = new List() { 2.0d, 1.5d, 1.25d, 1.0d, 0.75d, 0.5d }; /// /// 默认视频类型 int 1.0 /// + [SettingKey(typeof(int))] public const string DEFAULT_VIDEO_SPEED = "PlayerDefaultSpeed"; /// /// 播放模式 int 0=顺序播放,1=单集循环,2=列表循环 /// + [SettingKey(typeof(int))] public const string DEFAULT_PLAY_MODE = "PlayerDefaultPlayMode"; /// /// 音量 /// + [SettingKey(typeof(double))] public const string PLAYER_VOLUME = "PlayerVolume"; /// /// 亮度 /// + [SettingKey(typeof(double))] public const string PLAYER_BRIGHTNESS = "PlayeBrightness"; /// /// A-B 循环播放模式的播放记录 /// + [SettingKey(typeof(object))] public const string PLAYER_ABPLAY_HISTORIES = "PlayerABPlayHistories"; /// /// 字幕颜色 /// + [SettingKey(typeof(int))] public const string SUBTITLE_COLOR = "subtitleColor"; /// /// 字幕背景颜色 /// + [SettingKey(typeof(int))] public const string SUBTITLE_BORDER_COLOR = "subtitleBorderColor"; /// /// 字幕大小 /// + [SettingKey(typeof(double))] public const string SUBTITLE_SIZE = "subtitleSize"; /// /// 字幕显示 @@ -442,77 +537,95 @@ public class Player /// /// 字幕透明度 /// + [SettingKey(typeof(double))] public const string SUBTITLE_OPACITY = "subtitleOpacity"; /// /// 字幕底部距离 /// + [SettingKey(typeof(double))] public const string SUBTITLE_BOTTOM = "subtitleBottom"; /// /// 字幕加粗 /// + [SettingKey(typeof(bool))] public const string SUBTITLE_BOLD = "subtitleBold"; /// /// 字幕对齐 /// 0=居中对齐,1=左对齐,2=右对齐 /// + [SettingKey(typeof(int))] public const string SUBTITLE_ALIGN = "subtitleAlign"; /// /// 自动跳转进度 /// + [SettingKey(typeof(bool))] public const string AUTO_TO_POSITION = "PlayerAutoToPosition"; /// /// 自动铺满窗口 /// + [SettingKey(typeof(bool))] public const string AUTO_FULL_WINDOW = "PlayerAutoToFullWindow"; /// /// 自动铺满全屏 /// + [SettingKey(typeof(bool))] public const string AUTO_FULL_SCREEN = "PlayerAutoToFullScreen"; /// /// 双击全屏 /// + [SettingKey(typeof(bool))] public const string DOUBLE_CLICK_FULL_SCREEN = "PlayerDoubleClickFullScreen"; /// /// 方向键右键行为 /// + [SettingKey(typeof(int))] public const string PLAYER_KEY_RIGHT_ACTION = "PlayerKeyRightAction"; /// /// 按住手势行为 /// + [SettingKey(typeof(int))] public const string HOLDING_GESTURE_ACTION = "HoldingGestureAction"; /// /// 按住手势可被其他手势取消 /// + [SettingKey(typeof(bool))] public const string HOLDING_GESTURE_CAN_CANCEL = "HoldingGestureCanCancel"; /// /// 倍速播放速度 /// + [SettingKey(typeof(double))] public const string HIGH_RATE_PLAY_SPEED = "HighRatePlaySpeed"; + + [SettingDefaultValue] public static List HIGH_RATE_PLAY_SPEED_LIST = new List() { 3.0d, 2.0d }; /// /// 自动打开AI字幕 /// + [SettingKey(typeof(bool))] public const string AUTO_OPEN_AI_SUBTITLE = "PlayerAutoOpenAISubtitle"; /// /// 替换CDN /// + [SettingKey(typeof(int))] public const string REPLACE_CDN = "PlayerReplaceCDN"; /// /// CDN服务器 /// + [SettingKey] public const string CDN_SERVER = "PlayerCDNServer"; /// /// 直播播放器默认模式 /// + [SettingKey(typeof(int))] public const string DEFAULT_LIVE_PLAYER_MODE = "DefaultLivePlayerMode"; } @@ -525,30 +638,35 @@ public class Roaming /// /// 自定义服务器链接 /// + [SettingKey(typeof(string))] public const string CUSTOM_SERVER_URL = "RoamingCustomServerUrl"; /// /// 自定义香港服务器链接 /// + [SettingKey(typeof(string))] public const string CUSTOM_SERVER_URL_HK = "RoamingCustomServerUrlHK"; /// /// 自定义台湾服务器链接 /// + [SettingKey(typeof(string))] public const string CUSTOM_SERVER_URL_TW = "RoamingCustomServerUrlTW"; /// /// 自定义大陆服务器链接 /// + [SettingKey(typeof(string))] public const string CUSTOM_SERVER_URL_CN = "RoamingCustomServerUrlCN"; /// /// 简体中文 /// + [SettingKey(typeof(bool))] public const string TO_SIMPLIFIED = "RoamingSubtitleToSimplified"; - /// - /// 只使用AkamaiCDN链接 - /// + ///// + ///// 只使用AkamaiCDN链接 + ///// //public const string AKAMAI_CDN = "RoamingAkamaiCDN"; } @@ -557,36 +675,45 @@ public class Download /// /// 下载目录 /// + [SettingKey(typeof(string))] public const string DOWNLOAD_PATH = "downloadPath"; + [SettingDefaultValue] public const string DEFAULT_PATH = "视频库/哔哩哔哩下载"; /// /// 旧版下载目录 /// + [SettingKey(typeof(string))] public const string OLD_DOWNLOAD_PATH = "downloadOldPath"; + [SettingDefaultValue] public const string DEFAULT_OLD_PATH = "视频库/BiliBiliDownload"; /// /// 允许付费网络下载 /// + [SettingKey(typeof(bool))] public const string ALLOW_COST_NETWORK = "allowCostNetwork"; /// /// 并行下载 /// + [SettingKey(typeof(bool))] public const string PARALLEL_DOWNLOAD = "parallelDownload"; /// /// 并行下载 /// + [SettingKey(typeof(bool))] public const string SEND_TOAST = "sendToast"; /// /// 加载旧版下载视频 /// + [SettingKey(typeof(bool))] public const string LOAD_OLD_DOWNLOAD = "loadOldDownload"; /// /// 下载视频类型 /// + [SettingKey(typeof(int))] public const string DEFAULT_VIDEO_TYPE = "DownloadDefaultVideoType"; } @@ -644,6 +771,7 @@ public class Other /// /// 默认发起请求时使用的build值 /// + [SettingDefaultValue] public const string DEFAULT_REQUEST_BUILD = "75900200"; } } diff --git a/src/BiliLite.UWP/Pages/SettingPage.xaml b/src/BiliLite.UWP/Pages/SettingPage.xaml index 505e8a8e..73ff8c3d 100644 --- a/src/BiliLite.UWP/Pages/SettingPage.xaml +++ b/src/BiliLite.UWP/Pages/SettingPage.xaml @@ -600,6 +600,11 @@ + + + + + 更新json请求地址(用于解决github在国内访问不佳的问题) (); + await exportService.ExportSettings(); + } + + private async void BtnImportSettings_OnClick(object sender, RoutedEventArgs e) + { + var importService = App.ServiceProvider.GetRequiredService(); + await importService.ImportSettings(); + Notify.ShowMessageToast("导入成功,正在重启应用"); + // 等用户看提示 + await Task.Delay(3000); + var result = await CoreApplication.RequestRestartAsync(""); + + if (result == AppRestartFailureReason.NotInForeground || result == AppRestartFailureReason.Other) + { + Notify.ShowMessageToast("重启失败,请手动重启应用"); + } + } + + private async void BtnExportSettingsWithAccount_OnClick(object sender, RoutedEventArgs e) + { + var exportService = App.ServiceProvider.GetRequiredService(); + await exportService.ExportSettingsWithAccount(); + } } } diff --git a/src/BiliLite.UWP/Services/SettingService.cs b/src/BiliLite.UWP/Services/SettingService.cs index 17c599d7..37356911 100644 --- a/src/BiliLite.UWP/Services/SettingService.cs +++ b/src/BiliLite.UWP/Services/SettingService.cs @@ -25,6 +25,11 @@ public static void SetValue(string key, T value) storageHelper.Save(key, value); } + public static bool HasValue(string key) + { + return storageHelper.KeyExists(key); + } + public class UI { private static bool? _loadOriginalImage = null; diff --git a/src/BiliLite.UWP/Services/SettingsImportExportService.cs b/src/BiliLite.UWP/Services/SettingsImportExportService.cs new file mode 100644 index 00000000..23b24908 --- /dev/null +++ b/src/BiliLite.UWP/Services/SettingsImportExportService.cs @@ -0,0 +1,237 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Windows.Storage.Pickers; +using BiliLite.Models.Attributes; +using BiliLite.Models.Common; +using Newtonsoft.Json; +using Tomlyn; +using Tomlyn.Model; +using BiliLite.Extensions; +using System.Security.Cryptography; +using Windows.Storage; + +namespace BiliLite.Services +{ + public class SettingsImportExportService + { + private const string SettingsExportKey = "4bmsD9chgoP1jdohv2+OV9Pv2403r4IfJU18ixpFWQA="; + private const string SettingsExportIV = "ABxrLAWa7MrKg6w1xxtZmw=="; + + private AesCryptoServiceProvider aesProvider; + private ICryptoTransform encryptor; + private ICryptoTransform decryptor; + + public SettingsImportExportService() + { + aesProvider = new AesCryptoServiceProvider(); + aesProvider.Key = Convert.FromBase64String(SettingsExportKey); + aesProvider.IV = Convert.FromBase64String(SettingsExportIV); + aesProvider.Mode = CipherMode.CBC; + aesProvider.Padding = PaddingMode.PKCS7; + + encryptor = aesProvider.CreateEncryptor(aesProvider.Key, aesProvider.IV); + decryptor = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV); + } + + private void ExportSettingsCore(TomlTable model, Type settingsType) + { + var fields = settingsType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + foreach (var field in fields) + { + var attributes = field.GetCustomAttributes(false); + var keyAttribute = attributes.FirstOrDefault(x => x.GetType() == typeof(SettingKeyAttribute)); + if (!(keyAttribute is SettingKeyAttribute settingKeyAttribute)) continue; + var key = field.GetRawConstantValue().ToString(); + + if (!SettingService.HasValue(key)) continue; + + object value = null; + if (settingKeyAttribute.Type == typeof(string)) + { + value = SettingService.GetValue(key, ""); + } + else if (settingKeyAttribute.Type == typeof(int)) + { + value = SettingService.GetValue(key, 0); + } + else if (settingKeyAttribute.Type == typeof(long)) + { + value = SettingService.GetValue(key, 0); + } + else if (settingKeyAttribute.Type == typeof(double)) + { + value = SettingService.GetValue(key, 0); + } + else if (settingKeyAttribute.Type == typeof(object)) + { + value = SettingService.GetValue(key, null); + value = JsonConvert.SerializeObject(value); + } + else if (settingKeyAttribute.Type == typeof(bool)) + { + value = SettingService.GetValue(key, false); + } + + model[key] = value; + } + } + + private void ImportSettingsCore(TomlTable model, Type settingsType) + { + var fields = settingsType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + foreach (var field in fields) + { + var attributes = field.GetCustomAttributes(false); + var keyAttribute = attributes.FirstOrDefault(x => x.GetType() == typeof(SettingKeyAttribute)); + if (!(keyAttribute is SettingKeyAttribute settingKeyAttribute)) continue; + var key = field.GetRawConstantValue().ToString(); + + if (!model.ContainsKey(key)) continue; + + if (settingKeyAttribute.Type == typeof(object)) + { + var value = JsonConvert.DeserializeObject(model[key].ToString()); + SettingService.SetValue(key, value); + } + else if (settingKeyAttribute.Type == typeof(string)) + { + var value = model[key].ToString(); + SettingService.SetValue(key, value); + } + else if (settingKeyAttribute.Type == typeof(int)) + { + var value = model[key].ToInt32(); + SettingService.SetValue(key, value); + } + else if (settingKeyAttribute.Type == typeof(long)) + { + var value = model[key].ToInt64(); + SettingService.SetValue(key, value); + } + else if (settingKeyAttribute.Type == typeof(double)) + { + var value = (double)model[key]; + SettingService.SetValue(key, value); + } + else + { + SettingService.SetValue(key, model[key]); + } + } + } + + public byte[] EncryptToBinary(string plainText) + { + byte[] encrypted; + using var msEncrypt = new MemoryStream(); + using var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write); + using var swEncrypt = new StreamWriter(csEncrypt); + swEncrypt.Write(plainText); + encrypted = msEncrypt.ToArray(); + + return encrypted; + } + + public string DecryptFromBinary(byte[] cipherTextBinary) + { + string plaintext = null; + using var msDecrypt = new MemoryStream(cipherTextBinary); + using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read); + using var srDecrypt = new StreamReader(csDecrypt); + plaintext = srDecrypt.ReadToEnd(); + + return plaintext; + } + + private string Decode(byte[] bin) + { + var text = DecryptFromBinary(bin); + return text; + } + + private byte[] Encode(string text) + { + var bin = EncryptToBinary(text); + return bin; + } + + public async Task ExportSettings() + { + var folder = await new FolderPicker().PickSingleFolderAsync(); + if (folder == null) return; + var file = await folder.CreateFileAsync($"{DateTime.Now.ToString("yyyy-M-d-HH_mm_ss")}.bililiteSettings"); + + var model = Toml.ToModel(""); + + ExportSettingsCore(model, typeof(SettingConstants.UI)); + ExportSettingsCore(model, typeof(SettingConstants.VideoDanmaku)); + ExportSettingsCore(model, typeof(SettingConstants.Live)); + ExportSettingsCore(model, typeof(SettingConstants.Player)); + ExportSettingsCore(model, typeof(SettingConstants.Roaming)); + ExportSettingsCore(model, typeof(SettingConstants.Download)); + ExportSettingsCore(model, typeof(SettingConstants.Other)); + + var modelString = Toml.FromModel(model); + + var bin = Encode(modelString); + + using var stream = await file.OpenStreamForWriteAsync(); + await stream.WriteAsync(bin, 0, bin.Length); + await stream.FlushAsync(); + } + + public async Task ExportSettingsWithAccount() + { + var folder = await new FolderPicker().PickSingleFolderAsync(); + if (folder == null) return; + var file = await folder.CreateFileAsync($"{DateTime.Now.ToString("yyyy-M-d-HH_mm_ss")}.bililiteSettings"); + + var model = Toml.ToModel(""); + + ExportSettingsCore(model, typeof(SettingConstants.UI)); + ExportSettingsCore(model, typeof(SettingConstants.Account)); + ExportSettingsCore(model, typeof(SettingConstants.VideoDanmaku)); + ExportSettingsCore(model, typeof(SettingConstants.Live)); + ExportSettingsCore(model, typeof(SettingConstants.Player)); + ExportSettingsCore(model, typeof(SettingConstants.Roaming)); + ExportSettingsCore(model, typeof(SettingConstants.Download)); + ExportSettingsCore(model, typeof(SettingConstants.Other)); + + var modelString = Toml.FromModel(model); + + var bin = Encode(modelString); + + using var stream = await file.OpenStreamForWriteAsync(); + await stream.WriteAsync(bin, 0, bin.Length); + await stream.FlushAsync(); + } + + public async Task ImportSettings() + { + var filePicker = new FileOpenPicker(); + filePicker.FileTypeFilter.Add(".bililiteSettings"); + var file = await filePicker.PickSingleFileAsync(); + if (file == null) return; + using var openFile = await file.OpenAsync(FileAccessMode.Read); + using var stream = openFile.AsStreamForRead(); + var bin = new byte[stream.Length]; + + await stream.ReadAsync(bin, 0, bin.Length); + + var text = Decode(bin); + var model = Toml.ToModel(text); + + ImportSettingsCore(model, typeof(SettingConstants.UI)); + ImportSettingsCore(model, typeof(SettingConstants.Account)); + ImportSettingsCore(model, typeof(SettingConstants.VideoDanmaku)); + ImportSettingsCore(model, typeof(SettingConstants.Live)); + ImportSettingsCore(model, typeof(SettingConstants.Player)); + ImportSettingsCore(model, typeof(SettingConstants.Roaming)); + ImportSettingsCore(model, typeof(SettingConstants.Download)); + ImportSettingsCore(model, typeof(SettingConstants.Other)); + } + } +} diff --git a/src/BiliLite.UWP/Services/WbiKeyService.cs b/src/BiliLite.UWP/Services/WbiKeyService.cs index 3e645ee9..06dd62a4 100644 --- a/src/BiliLite.UWP/Services/WbiKeyService.cs +++ b/src/BiliLite.UWP/Services/WbiKeyService.cs @@ -36,7 +36,7 @@ private WbiKey GetCurrentWbiKeys() public async Task GetWbiKeys() { - var lastKeySaveTimestamp = SettingService.GetValue(SettingConstants.Account.WBI_KEY_TIME, 0); + var lastKeySaveTimestamp = SettingService.GetValue(SettingConstants.Account.WBI_KEY_TIME, 0); if (lastKeySaveTimestamp <= 0) return await GetNewWbiKeys(); var lastKeySaveTime = DateTimeOffset.FromUnixTimeSeconds(lastKeySaveTimestamp); if ((DateTimeOffset.Now - lastKeySaveTime) >= diff --git a/src/BiliLite.UWP/Startup.cs b/src/BiliLite.UWP/Startup.cs index 811ce56d..ed017e95 100644 --- a/src/BiliLite.UWP/Startup.cs +++ b/src/BiliLite.UWP/Startup.cs @@ -15,6 +15,7 @@ public void ConfigureServices(HostBuilderContext context, IServiceCollection ser services.AddDanmakuController(); services.AddSingleton(); + services.AddTransient(); services.AddQrCodeService(); services.AddSingleton(); From afd501c95d75ac3f40f2501e2af2ed5b6e97e5df Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Fri, 12 Apr 2024 20:15:47 +0800 Subject: [PATCH 02/30] =?UTF-8?q?=E4=B8=B4=E6=97=B6=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=8A=A8=E6=80=81Tab=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E6=89=93=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs b/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs index f5da85fa..6ffba5c4 100644 --- a/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs +++ b/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs @@ -46,7 +46,8 @@ public ApiModel DyanmicNew(UserDynamicType type) //使用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; From 002d31a639477ae1f3c9e3907094aec692a4af4b Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sun, 14 Apr 2024 15:07:48 +0800 Subject: [PATCH 03/30] =?UTF-8?q?=E4=B8=B4=E6=97=B6=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=8A=A8=E6=80=81Tab=E5=8F=AA=E8=83=BD?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E7=AC=AC=E4=B8=80=E9=A1=B5=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=B8=8E=E9=83=A8=E5=88=86=E5=8A=A8=E6=80=81=E4=B8=8D=E9=80=82?= =?UTF-8?q?=E9=85=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/Builders/DynamicItemDisplayModelBuilder.cs | 2 +- src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/BiliLite.UWP/Models/Builders/DynamicItemDisplayModelBuilder.cs b/src/BiliLite.UWP/Models/Builders/DynamicItemDisplayModelBuilder.cs index 821b3282..ab32b07b 100644 --- a/src/BiliLite.UWP/Models/Builders/DynamicItemDisplayModelBuilder.cs +++ b/src/BiliLite.UWP/Models/Builders/DynamicItemDisplayModelBuilder.cs @@ -82,7 +82,7 @@ public DynamicItemDisplayModelBuilder SwitchType(IMapper mapper, JObject card, J m_displayViewModel.ImagesInfo = imgs; break; } - case UserDynamicDisplayType.Repost when card.ContainsKey("origin_user"): + case UserDynamicDisplayType.Repost when card.ContainsKey("origin_user") && card["origin_user"].ToString() != string.Empty: { var originUser = JsonConvert.DeserializeObject(card["origin_user"].ToString()); var model = new DynamicCardModel diff --git a/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs b/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs index 6ffba5c4..f0dfc5fa 100644 --- a/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs +++ b/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs @@ -116,7 +116,8 @@ public ApiModel HistoryDynamic(string dynamic_id, UserDynamicType type) };//使用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; From edafa2fbfa7b7723c4ce1605eaa6a4202299d214 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Mon, 15 Apr 2024 12:15:16 +0800 Subject: [PATCH 04/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=95=AA=E5=89=A7?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=95=B0=E6=8D=AEint=E8=B6=8A=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/Common/Season/SeasonDetailStatModel.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/BiliLite.UWP/Models/Common/Season/SeasonDetailStatModel.cs b/src/BiliLite.UWP/Models/Common/Season/SeasonDetailStatModel.cs index f40534b0..777da5f5 100644 --- a/src/BiliLite.UWP/Models/Common/Season/SeasonDetailStatModel.cs +++ b/src/BiliLite.UWP/Models/Common/Season/SeasonDetailStatModel.cs @@ -2,20 +2,20 @@ { public class SeasonDetailStatModel { - public int Coins { get; set; } + public long Coins { get; set; } - public int Danmakus { get; set; } + public long Danmakus { get; set; } - public int Favorites { get; set; } + public long Favorites { get; set; } public string Followers { get; set; } public string Play { get; set; } - public int Reply { get; set; } + public long Reply { get; set; } - public int Share { get; set; } + public long Share { get; set; } - public int Views { get; set; } + public long Views { get; set; } } } \ No newline at end of file From fa7cd2b39bd65cf63b87e1f53081a203e396816a Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Mon, 15 Apr 2024 21:28:10 +0800 Subject: [PATCH 05/30] =?UTF-8?q?=E9=83=A8=E5=88=86=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E8=BF=87=E5=A4=A7=E7=9A=84=E6=95=B0=E5=80=BC=E6=94=B9=E4=B8=BA?= =?UTF-8?q?long=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/Common/Anime/AnimeRankModel.cs | 6 +++--- .../Models/Common/Dynamic/DynamicDescModel.cs | 6 +++--- .../Common/Dynamic/DynamicVideoCardStatModel.cs | 14 +++++++------- .../Common/Recommend/RecommendItemArgsModel.cs | 2 +- .../Common/Video/Detail/VideoDetailStatModel.cs | 16 ++++++++-------- src/BiliLite.UWP/Models/Dynamic/DynamicModel.cs | 8 ++++---- src/BiliLite.UWP/Modules/Home/CinemaVM.cs | 6 +++--- src/BiliLite.UWP/Modules/RankVM.cs | 16 ++++++++-------- src/BiliLite.UWP/Modules/SearchVM.cs | 6 +++--- src/BiliLite.UWP/Modules/Season/SeasonRankVM.cs | 6 +++--- .../User/UserDetail/UserSubmitArticleVM.cs | 14 +++++++------- .../ViewModels/Video/VideoDetailStatViewModel.cs | 16 ++++++++-------- 12 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/BiliLite.UWP/Models/Common/Anime/AnimeRankModel.cs b/src/BiliLite.UWP/Models/Common/Anime/AnimeRankModel.cs index 2526638d..15449ffa 100644 --- a/src/BiliLite.UWP/Models/Common/Anime/AnimeRankModel.cs +++ b/src/BiliLite.UWP/Models/Common/Anime/AnimeRankModel.cs @@ -16,11 +16,11 @@ public class AnimeRankModel : ISeasonItem [JsonProperty("index_show")] public string IndexShow { get; set; } - public int Follow { get; set; } + public long Follow { get; set; } - public int Danmaku { get; set; } + public long Danmaku { get; set; } - public int View { get; set; } + public long View { get; set; } [JsonProperty("show_badge")] public bool ShowBadge => !string.IsNullOrEmpty(Badge); diff --git a/src/BiliLite.UWP/Models/Common/Dynamic/DynamicDescModel.cs b/src/BiliLite.UWP/Models/Common/Dynamic/DynamicDescModel.cs index d6ad714d..3e212886 100644 --- a/src/BiliLite.UWP/Models/Common/Dynamic/DynamicDescModel.cs +++ b/src/BiliLite.UWP/Models/Common/Dynamic/DynamicDescModel.cs @@ -14,11 +14,11 @@ public class DynamicDescModel public string Rid { get; set; } - public int View { get; set; } + public long View { get; set; } - public int Like { get; set; } + public long Like { get; set; } - public int Comment { get; set; } + public long Comment { get; set; } [JsonProperty("is_liked")] public int IsLiked { get; set; } diff --git a/src/BiliLite.UWP/Models/Common/Dynamic/DynamicVideoCardStatModel.cs b/src/BiliLite.UWP/Models/Common/Dynamic/DynamicVideoCardStatModel.cs index 79d93dab..eb436cc7 100644 --- a/src/BiliLite.UWP/Models/Common/Dynamic/DynamicVideoCardStatModel.cs +++ b/src/BiliLite.UWP/Models/Common/Dynamic/DynamicVideoCardStatModel.cs @@ -2,18 +2,18 @@ { public class DynamicVideoCardStatModel { - public int Coin { get; set; } + public long Coin { get; set; } - public int Danmaku { get; set; } + public long Danmaku { get; set; } - public int Favorite { get; set; } + public long Favorite { get; set; } - public int Like { get; set; } + public long Like { get; set; } - public int Reply { get; set; } + public long Reply { get; set; } - public int Share { get; set; } + public long Share { get; set; } - public int View { get; set; } + public long View { get; set; } } } \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/Recommend/RecommendItemArgsModel.cs b/src/BiliLite.UWP/Models/Common/Recommend/RecommendItemArgsModel.cs index 734803ef..46c6929a 100644 --- a/src/BiliLite.UWP/Models/Common/Recommend/RecommendItemArgsModel.cs +++ b/src/BiliLite.UWP/Models/Common/Recommend/RecommendItemArgsModel.cs @@ -18,6 +18,6 @@ public class RecommendItemArgsModel public string Rname { get; set; } - public int Aid { get; set; } + public long Aid { get; set; } } } \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/Video/Detail/VideoDetailStatModel.cs b/src/BiliLite.UWP/Models/Common/Video/Detail/VideoDetailStatModel.cs index 2d7736be..ed0e2e14 100644 --- a/src/BiliLite.UWP/Models/Common/Video/Detail/VideoDetailStatModel.cs +++ b/src/BiliLite.UWP/Models/Common/Video/Detail/VideoDetailStatModel.cs @@ -9,42 +9,42 @@ public class VideoDetailStatModel /// /// 播放 /// - public int View { get; set; } + public long View { get; set; } /// /// 弹幕 /// - public int Danmaku { get; set; } + public long Danmaku { get; set; } /// /// 评论 /// - public int Reply { get; set; } + public long Reply { get; set; } /// /// 收藏 /// - public int Favorite { get; set; } + public long Favorite { get; set; } /// /// 投币 /// - public int Coin { get; set; } + public long Coin { get; set; } /// /// 分享 /// - public int Share { get; set; } + public long Share { get; set; } /// /// 点赞 /// - public int Like { get; set; } + public long Like { get; set; } /// /// 不喜欢,固定0 /// [JsonProperty("dislike")] - public int DisLike { get; set; } + public long DisLike { get; set; } } } \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Dynamic/DynamicModel.cs b/src/BiliLite.UWP/Models/Dynamic/DynamicModel.cs index 90d1111a..7586bf48 100644 --- a/src/BiliLite.UWP/Models/Dynamic/DynamicModel.cs +++ b/src/BiliLite.UWP/Models/Dynamic/DynamicModel.cs @@ -32,10 +32,10 @@ public class DynamicCardDescModel public string rid_str { get; set; } public int r_type { get; set; } public string bvid { get; set; } - public int view { get; set; } - public int repost { get; set; } - public int comment { get; set; } - public int like { get; set; } + public long view { get; set; } + public long repost { get; set; } + public long comment { get; set; } + public long like { get; set; } public int is_liked { get; set; } public long timestamp { get; set; } public string pre_dy_id { get; set; } diff --git a/src/BiliLite.UWP/Modules/Home/CinemaVM.cs b/src/BiliLite.UWP/Modules/Home/CinemaVM.cs index eefeb05e..87c80217 100644 --- a/src/BiliLite.UWP/Modules/Home/CinemaVM.cs +++ b/src/BiliLite.UWP/Modules/Home/CinemaVM.cs @@ -372,9 +372,9 @@ public bool ShowBadge } public class CinemaHomeStatModel { - public int view { get; set; } + public long view { get; set; } public string follow_view { get; set; } - public int follow { get; set; } - public int danmaku { get; set; } + public long follow { get; set; } + public long danmaku { get; set; } } } diff --git a/src/BiliLite.UWP/Modules/RankVM.cs b/src/BiliLite.UWP/Modules/RankVM.cs index 5188c83f..1b39cc5f 100644 --- a/src/BiliLite.UWP/Modules/RankVM.cs +++ b/src/BiliLite.UWP/Modules/RankVM.cs @@ -194,20 +194,20 @@ public class RankItemModel public RankItemOwnerModel owner { get; set; } public RankItemStatModel stat { get; set; } public string dynamic { get; set; } - public int cid { get; set; } + public long cid { get; set; } public string bvid { get; set; } public int score { get; set; } } public class RankItemStatModel { - public int aid { get; set; } - public int view { get; set; } - public int danmaku { get; set; } - public int reply { get; set; } - public int favorite { get; set; } - public int coin { get; set; } - public int share { get; set; } + public long aid { get; set; } + public long view { get; set; } + public long danmaku { get; set; } + public long reply { get; set; } + public long favorite { get; set; } + public long coin { get; set; } + public long share { get; set; } } public class RankItemOwnerModel { diff --git a/src/BiliLite.UWP/Modules/SearchVM.cs b/src/BiliLite.UWP/Modules/SearchVM.cs index 66c957b2..e9dd9309 100644 --- a/src/BiliLite.UWP/Modules/SearchVM.cs +++ b/src/BiliLite.UWP/Modules/SearchVM.cs @@ -1007,9 +1007,9 @@ public string title public string category_name { get; set; } public string type { get; set; } public string desc { get; set; } - public int like { get; set; } - public int view { get; set; } - public int reply { get; set; } + public long like { get; set; } + public long view { get; set; } + public long reply { get; set; } public string id { get; set; } public List image_urls { get; set; } public string cover diff --git a/src/BiliLite.UWP/Modules/Season/SeasonRankVM.cs b/src/BiliLite.UWP/Modules/Season/SeasonRankVM.cs index 8187f593..50ef7e7f 100644 --- a/src/BiliLite.UWP/Modules/Season/SeasonRankVM.cs +++ b/src/BiliLite.UWP/Modules/Season/SeasonRankVM.cs @@ -141,9 +141,9 @@ public class SeasonRankItemModel } public class SeasonRankItemStatModel { - public int danmaku { get; set; } - public int follow { get; set; } - public int view { get; set; } + public long danmaku { get; set; } + public long follow { get; set; } + public long view { get; set; } } public class SeasonRankItemNewEPModel { diff --git a/src/BiliLite.UWP/Modules/User/UserDetail/UserSubmitArticleVM.cs b/src/BiliLite.UWP/Modules/User/UserDetail/UserSubmitArticleVM.cs index 97300dad..3ca6b0d8 100644 --- a/src/BiliLite.UWP/Modules/User/UserDetail/UserSubmitArticleVM.cs +++ b/src/BiliLite.UWP/Modules/User/UserDetail/UserSubmitArticleVM.cs @@ -180,13 +180,13 @@ public string cover } public class SubmitArticleStatsModel { - public int view { get; set; } - public int favorite { get; set; } - public int like { get; set; } - public int reply { get; set; } - public int share { get; set; } - public int coin { get; set; } - public int dynamic { get; set; } + public long view { get; set; } + public long favorite { get; set; } + public long like { get; set; } + public long reply { get; set; } + public long share { get; set; } + public long coin { get; set; } + public long dynamic { get; set; } } public class SubmitArticleCategoryModel { diff --git a/src/BiliLite.UWP/ViewModels/Video/VideoDetailStatViewModel.cs b/src/BiliLite.UWP/ViewModels/Video/VideoDetailStatViewModel.cs index 72317112..da82b54b 100644 --- a/src/BiliLite.UWP/ViewModels/Video/VideoDetailStatViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/Video/VideoDetailStatViewModel.cs @@ -10,42 +10,42 @@ public class VideoDetailStatViewModel : BaseViewModel /// /// 播放 /// - public int View { get; set; } + public long View { get; set; } /// /// 弹幕 /// - public int Danmaku { get; set; } + public long Danmaku { get; set; } /// /// 评论 /// - public int Reply { get; set; } + public long Reply { get; set; } /// /// 收藏 /// - public int Favorite { get; set; } + public long Favorite { get; set; } /// /// 投币 /// - public int Coin { get; set; } + public long Coin { get; set; } /// /// 分享 /// - public int Share { get; set; } + public long Share { get; set; } /// /// 点赞 /// - public int Like { get; set; } + public long Like { get; set; } /// /// 不喜欢,固定0 /// [JsonProperty("dislike")] - public int DisLike { get; set; } + public long DisLike { get; set; } } } \ No newline at end of file From 75cc750936ea03e84beeec6f184dfc2c4cb26f41 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Tue, 16 Apr 2024 20:14:14 +0800 Subject: [PATCH 06/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/BiliLite.UWP.csproj | 3 + src/BiliLite.UWP/Pages/SettingPage.xaml.cs | 5 +- .../Services/SettingsImportExportService.cs | 164 ++++++++++-------- 3 files changed, 99 insertions(+), 73 deletions(-) diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj index da65e985..55cf7ab5 100644 --- a/src/BiliLite.UWP/BiliLite.UWP.csproj +++ b/src/BiliLite.UWP/BiliLite.UWP.csproj @@ -1325,6 +1325,9 @@ 107.3.0 + + 2.0.2 + 1.0.7 diff --git a/src/BiliLite.UWP/Pages/SettingPage.xaml.cs b/src/BiliLite.UWP/Pages/SettingPage.xaml.cs index 6f9ed0be..51e281e9 100644 --- a/src/BiliLite.UWP/Pages/SettingPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/SettingPage.xaml.cs @@ -1083,7 +1083,10 @@ private async void BtnExportSettings_OnClick(object sender, RoutedEventArgs e) private async void BtnImportSettings_OnClick(object sender, RoutedEventArgs e) { var importService = App.ServiceProvider.GetRequiredService(); - await importService.ImportSettings(); + if (!await importService.ImportSettings()) + { + return; + } Notify.ShowMessageToast("导入成功,正在重启应用"); // 等用户看提示 await Task.Delay(3000); diff --git a/src/BiliLite.UWP/Services/SettingsImportExportService.cs b/src/BiliLite.UWP/Services/SettingsImportExportService.cs index 23b24908..963fb4ed 100644 --- a/src/BiliLite.UWP/Services/SettingsImportExportService.cs +++ b/src/BiliLite.UWP/Services/SettingsImportExportService.cs @@ -12,28 +12,28 @@ using BiliLite.Extensions; using System.Security.Cryptography; using Windows.Storage; +using ArtisanCode.SimpleAesEncryption; namespace BiliLite.Services { public class SettingsImportExportService { - private const string SettingsExportKey = "4bmsD9chgoP1jdohv2+OV9Pv2403r4IfJU18ixpFWQA="; - private const string SettingsExportIV = "ABxrLAWa7MrKg6w1xxtZmw=="; - - private AesCryptoServiceProvider aesProvider; - private ICryptoTransform encryptor; - private ICryptoTransform decryptor; + private static readonly ILogger _logger = GlobalLogger.FromCurrentType(); + private const string SETTINGS_EXPORT_KEY = "4bmsD9chgoP1jdohv2+OV9Pv2403r4IfJU18ixpFWQA="; + private const string SETTINGS_EXPORT_IV = "ABxrLAWa7MrKg6w1xxtZmw=="; + private readonly RijndaelMessageEncryptor m_encryptor; + private readonly RijndaelMessageDecryptor m_decryptor; public SettingsImportExportService() { - aesProvider = new AesCryptoServiceProvider(); - aesProvider.Key = Convert.FromBase64String(SettingsExportKey); - aesProvider.IV = Convert.FromBase64String(SettingsExportIV); - aesProvider.Mode = CipherMode.CBC; - aesProvider.Padding = PaddingMode.PKCS7; - - encryptor = aesProvider.CreateEncryptor(aesProvider.Key, aesProvider.IV); - decryptor = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV); + var config = new SimpleAesEncryptionConfiguration() + { + CipherMode = CipherMode.CBC, + Padding = PaddingMode.PKCS7, + EncryptionKey = new EncryptionKeyConfigurationElement(256, SETTINGS_EXPORT_KEY), + }; + m_encryptor = new RijndaelMessageEncryptor(config); + m_decryptor = new RijndaelMessageDecryptor(config); } private void ExportSettingsCore(TomlTable model, Type settingsType) @@ -125,24 +125,14 @@ private void ImportSettingsCore(TomlTable model, Type settingsType) public byte[] EncryptToBinary(string plainText) { - byte[] encrypted; - using var msEncrypt = new MemoryStream(); - using var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write); - using var swEncrypt = new StreamWriter(csEncrypt); - swEncrypt.Write(plainText); - encrypted = msEncrypt.ToArray(); - - return encrypted; + var cyphertext = m_encryptor.Encrypt(plainText); + return System.Text.Encoding.UTF8.GetBytes(cyphertext); } public string DecryptFromBinary(byte[] cipherTextBinary) { - string plaintext = null; - using var msDecrypt = new MemoryStream(cipherTextBinary); - using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read); - using var srDecrypt = new StreamReader(csDecrypt); - plaintext = srDecrypt.ReadToEnd(); - + var binText = System.Text.Encoding.UTF8.GetString(cipherTextBinary); + var plaintext = m_decryptor.Decrypt(binText); return plaintext; } @@ -158,80 +148,110 @@ private byte[] Encode(string text) return bin; } - public async Task ExportSettings() + public async Task ExportSettings() { var folder = await new FolderPicker().PickSingleFolderAsync(); - if (folder == null) return; + if (folder == null) return false; var file = await folder.CreateFileAsync($"{DateTime.Now.ToString("yyyy-M-d-HH_mm_ss")}.bililiteSettings"); - var model = Toml.ToModel(""); + try + { + var model = Toml.ToModel(""); - ExportSettingsCore(model, typeof(SettingConstants.UI)); - ExportSettingsCore(model, typeof(SettingConstants.VideoDanmaku)); - ExportSettingsCore(model, typeof(SettingConstants.Live)); - ExportSettingsCore(model, typeof(SettingConstants.Player)); - ExportSettingsCore(model, typeof(SettingConstants.Roaming)); - ExportSettingsCore(model, typeof(SettingConstants.Download)); - ExportSettingsCore(model, typeof(SettingConstants.Other)); + ExportSettingsCore(model, typeof(SettingConstants.UI)); + ExportSettingsCore(model, typeof(SettingConstants.VideoDanmaku)); + ExportSettingsCore(model, typeof(SettingConstants.Live)); + ExportSettingsCore(model, typeof(SettingConstants.Player)); + ExportSettingsCore(model, typeof(SettingConstants.Roaming)); + ExportSettingsCore(model, typeof(SettingConstants.Download)); + ExportSettingsCore(model, typeof(SettingConstants.Other)); - var modelString = Toml.FromModel(model); + var modelString = Toml.FromModel(model); - var bin = Encode(modelString); + var bin = Encode(modelString); - using var stream = await file.OpenStreamForWriteAsync(); - await stream.WriteAsync(bin, 0, bin.Length); - await stream.FlushAsync(); + using var stream = await file.OpenStreamForWriteAsync(); + await stream.WriteAsync(bin, 0, bin.Length); + await stream.FlushAsync(); + return true; + } + catch (Exception ex) + { + _logger.Error("导出失败", ex); + Notify.ShowMessageToast("导出失败,已记录错误"); + return false; + } } - public async Task ExportSettingsWithAccount() + public async Task ExportSettingsWithAccount() { var folder = await new FolderPicker().PickSingleFolderAsync(); - if (folder == null) return; + if (folder == null) return false; var file = await folder.CreateFileAsync($"{DateTime.Now.ToString("yyyy-M-d-HH_mm_ss")}.bililiteSettings"); - var model = Toml.ToModel(""); + try + { + var model = Toml.ToModel(""); - ExportSettingsCore(model, typeof(SettingConstants.UI)); - ExportSettingsCore(model, typeof(SettingConstants.Account)); - ExportSettingsCore(model, typeof(SettingConstants.VideoDanmaku)); - ExportSettingsCore(model, typeof(SettingConstants.Live)); - ExportSettingsCore(model, typeof(SettingConstants.Player)); - ExportSettingsCore(model, typeof(SettingConstants.Roaming)); - ExportSettingsCore(model, typeof(SettingConstants.Download)); - ExportSettingsCore(model, typeof(SettingConstants.Other)); + ExportSettingsCore(model, typeof(SettingConstants.UI)); + ExportSettingsCore(model, typeof(SettingConstants.Account)); + ExportSettingsCore(model, typeof(SettingConstants.VideoDanmaku)); + ExportSettingsCore(model, typeof(SettingConstants.Live)); + ExportSettingsCore(model, typeof(SettingConstants.Player)); + ExportSettingsCore(model, typeof(SettingConstants.Roaming)); + ExportSettingsCore(model, typeof(SettingConstants.Download)); + ExportSettingsCore(model, typeof(SettingConstants.Other)); - var modelString = Toml.FromModel(model); + var modelString = Toml.FromModel(model); - var bin = Encode(modelString); + var bin = Encode(modelString); - using var stream = await file.OpenStreamForWriteAsync(); - await stream.WriteAsync(bin, 0, bin.Length); - await stream.FlushAsync(); + using var stream = await file.OpenStreamForWriteAsync(); + await stream.WriteAsync(bin, 0, bin.Length); + await stream.FlushAsync(); + return true; + } + catch (Exception ex) + { + _logger.Error("导出失败", ex); + Notify.ShowMessageToast("导出失败,已记录错误"); + return false; + } } - public async Task ImportSettings() + public async Task ImportSettings() { var filePicker = new FileOpenPicker(); filePicker.FileTypeFilter.Add(".bililiteSettings"); var file = await filePicker.PickSingleFileAsync(); - if (file == null) return; + if (file == null) return false; using var openFile = await file.OpenAsync(FileAccessMode.Read); using var stream = openFile.AsStreamForRead(); var bin = new byte[stream.Length]; await stream.ReadAsync(bin, 0, bin.Length); - var text = Decode(bin); - var model = Toml.ToModel(text); - - ImportSettingsCore(model, typeof(SettingConstants.UI)); - ImportSettingsCore(model, typeof(SettingConstants.Account)); - ImportSettingsCore(model, typeof(SettingConstants.VideoDanmaku)); - ImportSettingsCore(model, typeof(SettingConstants.Live)); - ImportSettingsCore(model, typeof(SettingConstants.Player)); - ImportSettingsCore(model, typeof(SettingConstants.Roaming)); - ImportSettingsCore(model, typeof(SettingConstants.Download)); - ImportSettingsCore(model, typeof(SettingConstants.Other)); + try + { + var text = Decode(bin); + var model = Toml.ToModel(text); + + ImportSettingsCore(model, typeof(SettingConstants.UI)); + ImportSettingsCore(model, typeof(SettingConstants.Account)); + ImportSettingsCore(model, typeof(SettingConstants.VideoDanmaku)); + ImportSettingsCore(model, typeof(SettingConstants.Live)); + ImportSettingsCore(model, typeof(SettingConstants.Player)); + ImportSettingsCore(model, typeof(SettingConstants.Roaming)); + ImportSettingsCore(model, typeof(SettingConstants.Download)); + ImportSettingsCore(model, typeof(SettingConstants.Other)); + } + catch (Exception ex) + { + _logger.Error("导入失败", ex); + Notify.ShowMessageToast("导入失败,已记录错误"); + return false; + } + return true; } } } From 22453178d2922b3a6c8834c5034332ed578f9489 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Tue, 16 Apr 2024 20:15:33 +0800 Subject: [PATCH 07/30] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=A9=BA=E9=97=B4?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E9=A1=B5=E6=81=A2=E5=A4=8D=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=E5=9B=BE=E6=A0=87=E3=80=81=E5=A4=B4=E5=83=8F?= =?UTF-8?q?=E8=A3=85=E9=A5=B0=E3=80=81=E5=8A=A8=E6=80=81=E8=A3=85=E9=A5=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dynamic/DynamicItemV2Control.xaml | 4 +++ .../UserDynamic/DynamicV2ItemViewModel.cs | 29 +++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml index b638f5ad..80e0ca66 100644 --- a/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml @@ -56,6 +56,10 @@ + + + + ImageInfos } [DoNotNotify] - public string Verify { get; set; } = Constants.App.TRANSPARENT_IMAGE; + public string Verify + { + get + { + if (Author == null) return Constants.App.TRANSPARENT_IMAGE; + return Author.Author.Official.Type switch + { + 1 => Constants.App.VERIFY_OGANIZATION_IMAGE, + 0 => Constants.App.VERIFY_PERSONAL_IMAGE, + -1 => Constants.App.TRANSPARENT_IMAGE, + _ => Constants.App.TRANSPARENT_IMAGE + }; + } + } [DoNotNotify] - public string Pendant { get; set; } = Constants.App.TRANSPARENT_IMAGE; + public string Pendant + { + get + { + if (Author == null) return Constants.App.TRANSPARENT_IMAGE; + if (Author.Author.Pendant != null && !string.IsNullOrEmpty(Author.Author.Pendant.Image)) + { + return Author.Author.Pendant.Image; + } + + return Constants.App.TRANSPARENT_IMAGE; + } + } } } \ No newline at end of file From 4fdaf37ce46d50e5201e8194d94b71006b3a3e3e Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Tue, 16 Apr 2024 22:24:59 +0800 Subject: [PATCH 08/30] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=8A=A8=E6=80=81Tab?= =?UTF-8?q?=E9=A1=B5=E6=9B=B4=E6=8D=A2=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/BiliLite.UWP.csproj | 9 + .../Extensions/ViewModelExtensions.cs | 1 + .../Models/Common/Home/DefaultHomeNavItems.cs | 31 +- .../UserDynamic/IUserDynamicCommands.cs | 31 ++ .../Pages/Home/UserDynamicAllPage.xaml | 175 ++++++++++ .../Pages/Home/UserDynamicAllPage.xaml.cs | 175 ++++++++++ src/BiliLite.UWP/Services/GrpcService.cs | 9 +- .../ViewModels/Home/HomeViewModel.cs | 1 + .../UserDynamic/DynamicV2ItemViewModel.cs | 2 +- .../UserDynamic/UserDynamicAllViewModel.cs | 316 ++++++++++++++++++ .../UserDynamic/UserDynamicSpaceViewModel.cs | 2 +- 11 files changed, 745 insertions(+), 7 deletions(-) create mode 100644 src/BiliLite.UWP/Models/Common/UserDynamic/IUserDynamicCommands.cs create mode 100644 src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml create mode 100644 src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs create mode 100644 src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj index 55cf7ab5..3048c446 100644 --- a/src/BiliLite.UWP/BiliLite.UWP.csproj +++ b/src/BiliLite.UWP/BiliLite.UWP.csproj @@ -158,11 +158,15 @@ + + + UserDynamicAllPage.xaml + @@ -216,6 +220,7 @@ DynamicSpacePage.xaml + @@ -969,6 +974,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + Designer MSBuild:Compile diff --git a/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs b/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs index 1b309f2d..0ffd7fd9 100644 --- a/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs +++ b/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs @@ -34,6 +34,7 @@ public static IServiceCollection AddViewModels(this IServiceCollection services) services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); return services; } } diff --git a/src/BiliLite.UWP/Models/Common/Home/DefaultHomeNavItems.cs b/src/BiliLite.UWP/Models/Common/Home/DefaultHomeNavItems.cs index 829c070c..f48fa0b9 100644 --- a/src/BiliLite.UWP/Models/Common/Home/DefaultHomeNavItems.cs +++ b/src/BiliLite.UWP/Models/Common/Home/DefaultHomeNavItems.cs @@ -1,9 +1,26 @@ -using System.Collections.Generic; +using BiliLite.Services; +using System.Collections.Generic; +using System.Linq; namespace BiliLite.Models.Common.Home { public static class DefaultHomeNavItems { + public static List CheckHomeNavItems(List navList) + { + var defaultItems = GetDefaultHomeNavItems(); + defaultItems.AddRange(GetDefaultHideHomeNavItems()); + var result = new List(navList); + foreach (var homeNavItem in navList.Where(homeNavItem => + defaultItems.All(x => x.Title != homeNavItem.Title || x.Page != homeNavItem.Page))) + { + result.Remove(homeNavItem); + } + SettingService.SetValue(SettingConstants.UI.HOEM_ORDER, result); + + return result; + } + public static List GetDefaultHomeNavItems() { return new List() @@ -27,7 +44,7 @@ public static List GetDefaultHomeNavItems() new HomeNavItem() { Icon = FontAwesome5.EFontAwesomeIcon.Solid_Heart, - Page = typeof(Pages.Home.UserDynamicPage), + Page = typeof(Pages.Home.UserDynamicAllPage), Title = "动态", NeedLogin = true, Show = false @@ -143,7 +160,15 @@ public static List GetDefaultHideHomeNavItems() Title = "我的收藏", NeedLogin = true, Show = false - } + }, + new HomeNavItem() + { + Icon = FontAwesome5.EFontAwesomeIcon.Solid_Heart, + Page = typeof(Pages.Home.UserDynamicPage), + Title = "动态(旧版)", + NeedLogin = true, + Show = false + }, }; } } diff --git a/src/BiliLite.UWP/Models/Common/UserDynamic/IUserDynamicCommands.cs b/src/BiliLite.UWP/Models/Common/UserDynamic/IUserDynamicCommands.cs new file mode 100644 index 00000000..61dce016 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/UserDynamic/IUserDynamicCommands.cs @@ -0,0 +1,31 @@ +using System.Windows.Input; + +namespace BiliLite.Models.Common.UserDynamic +{ + public interface IUserDynamicCommands + { + 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; } + + 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; } + } +} diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml new file mode 100644 index 00000000..20e6775d --- /dev/null +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Visible + + + + + Collapsed + + + + + + + + + + + + + + + Collapsed + + + + + Visible + + + + + + + + + + + + + + + + + + + + + + + + + + + 全部 + + + + + 投稿视频 + + + + + 追番追剧 + + + + + 专栏 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs new file mode 100644 index 00000000..d3cbbdd1 --- /dev/null +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs @@ -0,0 +1,175 @@ +using System.Linq; +using BiliLite.Services; +using BiliLite.Models.Common; +using BiliLite.Models.Requests.Api; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; +using BiliLite.Extensions; +using BiliLite.ViewModels.UserDynamic; +using Microsoft.Extensions.DependencyInjection; +using BiliLite.Models.Common.Comment; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media.Animation; + +// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 + +namespace BiliLite.Pages.Home +{ + /// + /// 可用于自身或导航至 Frame 内部的空白页。 + /// + public sealed partial class UserDynamicAllPage : Page + { + readonly UserDynamicAllViewModel m_viewModel; + private bool m_isStaggered = false; + + public UserDynamicAllPage() + { + m_viewModel = App.ServiceProvider.GetRequiredService(); + m_viewModel.OpenCommentEvent += UserDynamicViewModelOpenCommentEvent; + this.InitializeComponent(); + } + + protected override async void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + + SetStaggered(); + if (e.NavigationMode == NavigationMode.New && m_viewModel.DynamicItems == null) + { + await m_viewModel.GetDynamicItems(); + if (SettingService.GetValue("动态切换提示", true) && SettingService.GetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0) != 1) + { + SettingService.SetValue("动态切换提示", false); + Notify.ShowMessageToast("右下角可以切换成瀑布流显示哦~", 5); + } + } + } + + 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"]; + } + + 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 Pivot_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + //throw new System.NotImplementedException(); + } + + 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/Services/GrpcService.cs b/src/BiliLite.UWP/Services/GrpcService.cs index 5dcd9ccb..86227020 100644 --- a/src/BiliLite.UWP/Services/GrpcService.cs +++ b/src/BiliLite.UWP/Services/GrpcService.cs @@ -40,12 +40,17 @@ public async Task SearchSpaceArchive(string mid, int page = } } - public async Task GetDynAll(int page = 1) + public async Task GetDynAll(int page = 1, string offset = null) { var message = new DynAllReq() { - Page = page + Page = page, }; + if (offset != null) + { + message.Offset = offset; + message.RefreshType = Refresh.History; + } var requestUserInfo = new GrpcBiliUserInfo( SettingService.Account.AccessKey, SettingService.Account.UserID, diff --git a/src/BiliLite.UWP/ViewModels/Home/HomeViewModel.cs b/src/BiliLite.UWP/ViewModels/Home/HomeViewModel.cs index 026eef5f..b7a8694f 100644 --- a/src/BiliLite.UWP/ViewModels/Home/HomeViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/Home/HomeViewModel.cs @@ -27,6 +27,7 @@ public HomeViewModel() m_account = new Account(); m_mapper = App.ServiceProvider.GetRequiredService(); var homeNavItemList = SettingService.GetValue(SettingConstants.UI.HOEM_ORDER, DefaultHomeNavItems.GetDefaultHomeNavItems()); + homeNavItemList = DefaultHomeNavItems.CheckHomeNavItems(homeNavItemList); HomeNavItems = m_mapper.Map>(homeNavItemList); SelectItem = HomeNavItems.FirstOrDefault(); if (!SettingService.Account.Logined) return; diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs index 312c3da9..7fea8f42 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs @@ -25,7 +25,7 @@ public DynamicV2ItemViewModel() m_mapper = App.ServiceProvider.GetRequiredService(); } - public UserDynamicSpaceViewModel Parent { get; set; } + public IUserDynamicCommands Parent { get; set; } public string CardType { get; set; } diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs new file mode 100644 index 00000000..1000beeb --- /dev/null +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs @@ -0,0 +1,316 @@ +using AutoMapper; +using BiliLite.Models.Exceptions; +using BiliLite.Models.Requests.Api.User; +using BiliLite.Modules.User; +using BiliLite.Services; +using BiliLite.ViewModels.Common; +using System; +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using System.Windows.Input; +using BiliLite.Extensions; +using Bilibili.App.Dynamic.V2; +using System.Collections.Generic; +using System.Linq; +using Windows.UI.Xaml.Controls; +using BiliLite.Dialogs; +using BiliLite.Models; +using BiliLite.Models.Common; +using BiliLite.Models.Common.UserDynamic; +using BiliLite.Modules; +using BiliLite.Pages; +using BiliLite.Pages.User; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; + +namespace BiliLite.ViewModels.UserDynamic +{ + public class UserDynamicAllViewModel : BaseViewModel, IUserDynamicCommands + { + #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 UserDynamicAllViewModel(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 Loading { get; set; } + + public bool CanLoadMore { 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 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() ? "已复制" : "复制失败"); + } + + private void HandleDynamicResults(DynAllReply results) + { + CanLoadMore = results.DynamicList.HasMore; + m_offset = results.DynamicList.HistoryOffset; + var items = m_mapper.Map>(results.DynamicList.List.ToList()); + foreach (var item in items) + { + item.Parent = this; + } + if (m_page == 1) + DynamicItems = new ObservableCollection(items); + else + { + DynamicItems.AddRange(items); + } + } + + #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.GetDynAll(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/UserDynamicSpaceViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs index 73396fd4..8a4e15f0 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs @@ -25,7 +25,7 @@ namespace BiliLite.ViewModels.UserDynamic { - public class UserDynamicSpaceViewModel : BaseViewModel + public class UserDynamicSpaceViewModel : BaseViewModel, IUserDynamicCommands { #region Fields From cd872b4e146e5830e55a172bf98fb4a02dddb99d Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Wed, 17 Apr 2024 20:39:35 +0800 Subject: [PATCH 09/30] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E6=9B=B4=E6=8D=A2?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=9A=84=E9=A6=96=E9=A1=B5=E5=8A=A8=E6=80=81?= =?UTF-8?q?Tab=E9=A1=B5=E7=9A=84=E8=A7=86=E9=A2=91=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E5=92=8C=E7=95=AA=E5=89=A7=E5=8A=A8=E6=80=81=EF=BC=9B=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E8=BD=AC=E5=8F=91=E7=9A=84=E5=B7=B2=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E4=B8=8D=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/BiliLite.UWP.csproj | 1 + .../UserDynamicItemV2DataTemplateSelector.cs | 3 + .../Controls/Dynamic/DynamicV2Template.xaml | 79 ++++++++++++++----- .../Extensions/MapperExtensions.cs | 3 + src/BiliLite.UWP/Models/Common/Constants.cs | 2 + src/BiliLite.UWP/Models/Common/Enumerates.cs | 8 ++ .../UserDynamic/UserDynamicSeasonInfo.cs | 36 +++++++++ .../Pages/Home/UserDynamicAllPage.xaml | 3 +- .../Pages/Home/UserDynamicAllPage.xaml.cs | 11 ++- .../UserDynamic/DynamicV2ItemViewModel.cs | 6 ++ .../UserDynamic/UserDynamicAllViewModel.cs | 58 +++++++++++++- 11 files changed, 185 insertions(+), 25 deletions(-) create mode 100644 src/BiliLite.UWP/Models/Common/UserDynamic/UserDynamicSeasonInfo.cs diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj index 3048c446..49bb98d1 100644 --- a/src/BiliLite.UWP/BiliLite.UWP.csproj +++ b/src/BiliLite.UWP/BiliLite.UWP.csproj @@ -159,6 +159,7 @@ + diff --git a/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs index 54f8981a..56b20bc4 100644 --- a/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs +++ b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs @@ -38,6 +38,7 @@ DataTemplate SelectRowTemplate(UserDynamicItemDataTemplateSelector selector, { Constants.DynamicTypes.MUSIC, (selector, model) => selector.MusicTemplate }, { Constants.DynamicTypes.COMMON_SQUARE, (selector, model) => selector.CommonSquareTemplate }, { Constants.DynamicTypes.LIVE_RCMD, (selector, model) => selector.LiveRcmdTemplate }, + { Constants.DynamicTypes.CUSTOM_SEASON, (selector, model) => selector.CustomSeasonTemplate }, }; } @@ -63,6 +64,8 @@ DataTemplate SelectRowTemplate(UserDynamicItemDataTemplateSelector selector, public DataTemplate LiveRcmdTemplate { get; set; } + public DataTemplate CustomSeasonTemplate { get; set; } + public DataTemplate OtherTemplate { get; set; } protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml index 07f91c81..d6021e7f 100644 --- a/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml @@ -16,7 +16,8 @@ Draw2x2Template="{StaticResource DynamicDraw2x2}" Draw3x3Template="{StaticResource DynamicDraw3x3}" CommonSquareTemplate="{StaticResource DynamicCommonSquare}" - LiveRcmdTemplate="{StaticResource DynamicLiveRcmd}"> + LiveRcmdTemplate="{StaticResource DynamicLiveRcmd}" + CustomSeasonTemplate="{StaticResource DynamicCustomSeason}"> @@ -147,23 +148,37 @@ - - - - - - - + + + + + + + + + + + + + 资源已失效 + + + @@ -340,6 +355,34 @@ + + + + + + diff --git a/src/BiliLite.UWP/Extensions/MapperExtensions.cs b/src/BiliLite.UWP/Extensions/MapperExtensions.cs index 60751366..239a4867 100644 --- a/src/BiliLite.UWP/Extensions/MapperExtensions.cs +++ b/src/BiliLite.UWP/Extensions/MapperExtensions.cs @@ -145,6 +145,9 @@ public static IServiceCollection AddMapper(this IServiceCollection services) .ForMember(dest => dest.Stat, opt => opt.MapFrom(src => src.Modules.FirstOrDefault(x => x.ModuleType == DynModuleType.ModuleStat).ModuleStat)); + + expression.CreateMap(); + expression.CreateMap(); })); services.AddSingleton(mapper); diff --git a/src/BiliLite.UWP/Models/Common/Constants.cs b/src/BiliLite.UWP/Models/Common/Constants.cs index 6fce164c..2ed2ab0f 100644 --- a/src/BiliLite.UWP/Models/Common/Constants.cs +++ b/src/BiliLite.UWP/Models/Common/Constants.cs @@ -101,6 +101,8 @@ public static class DynamicTypes public const string COMMON_SQUARE = "CommonSquare"; public const string LIVE_RCMD = "LiveRcmd"; + + public const string CUSTOM_SEASON = "CustomSeason"; } } } diff --git a/src/BiliLite.UWP/Models/Common/Enumerates.cs b/src/BiliLite.UWP/Models/Common/Enumerates.cs index 5e61cd59..a8d96782 100644 --- a/src/BiliLite.UWP/Models/Common/Enumerates.cs +++ b/src/BiliLite.UWP/Models/Common/Enumerates.cs @@ -435,4 +435,12 @@ public enum SeasonIdType SeasonId, EpId, } + + public enum UserDynamicShowType + { + All = 0, + Video = 1, + Season = 2, + Article = 3 + } } \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/UserDynamic/UserDynamicSeasonInfo.cs b/src/BiliLite.UWP/Models/Common/UserDynamic/UserDynamicSeasonInfo.cs new file mode 100644 index 00000000..7e5a0edc --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/UserDynamic/UserDynamicSeasonInfo.cs @@ -0,0 +1,36 @@ +using BiliLite.ViewModels.UserDynamic; + +namespace BiliLite.Models.Common.UserDynamic +{ + public class UserDynamicSeasonInfo + { + public string SeasonId { get; set; } + + public string Url { get; set; } + + public string Cover { get; set; } + + public string Title { get; set; } + + public string SubTitle { get; set; } + + public UserDynamicSeasonNewEpInfo NewEp { get; set; } + + public DynamicV2ItemViewModel ToDynamicItem() + { + var item = new DynamicV2ItemViewModel() + { + CardType = Constants.DynamicTypes.CUSTOM_SEASON, + Season = this + }; + return item; + } + } + + public class UserDynamicSeasonNewEpInfo + { + public string IndexShow { get; set; } + + public string Cover { get; set; } + } +} diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml index 20e6775d..e35991bc 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml @@ -82,7 +82,7 @@ - + @@ -138,6 +138,7 @@ + diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs index d3cbbdd1..46f524cd 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs @@ -23,12 +23,14 @@ public sealed partial class UserDynamicAllPage : Page { readonly UserDynamicAllViewModel m_viewModel; private bool m_isStaggered = false; + private UserDynamicShowType m_currentShowType; public UserDynamicAllPage() { m_viewModel = App.ServiceProvider.GetRequiredService(); m_viewModel.OpenCommentEvent += UserDynamicViewModelOpenCommentEvent; this.InitializeComponent(); + m_currentShowType = (UserDynamicShowType)DynPivot.SelectedIndex; } protected override async void OnNavigatedTo(NavigationEventArgs e) @@ -85,7 +87,7 @@ private void SetListCore() private async void BtnRefreshDynamic_OnClick(object sender, RoutedEventArgs e) { - await m_viewModel.GetDynamicItems(); + await m_viewModel.GetDynamicItems(showType: m_currentShowType); } private void BtnTop_OnClick(object sender, RoutedEventArgs e) @@ -105,9 +107,12 @@ private void BtnGrid_OnClick(object sender, RoutedEventArgs e) SetGridCore(); } - private void Pivot_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + private async void Pivot_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { - //throw new System.NotImplementedException(); + var showType = (UserDynamicShowType)DynPivot.SelectedIndex; + if (showType == m_currentShowType) return; + m_currentShowType = showType; + await m_viewModel.GetDynamicItems(showType: showType); } private void CloseCommentCore() diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs index 7fea8f42..7f95a517 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs @@ -35,6 +35,8 @@ public DynamicV2ItemViewModel() public ModuleAuthorForward AuthorForward { get; set; } + public UserDynamicSeasonInfo Season { get; set; } + public ModuleDynamic Dynamic { get @@ -62,12 +64,16 @@ public ModuleDynamic Dynamic public ModuleOpusSummary OpusSummary { get; set; } + [DependsOn(nameof(Item))] + public bool ForwardMissed => Item == null; + public DynamicV2ItemViewModel Item { get; set; } public List Items { get { + if (Item == null) return null; Item.Parent = Parent; return new List() { diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs index 1000beeb..b6675240 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs @@ -36,6 +36,7 @@ public class UserDynamicAllViewModel : BaseViewModel, IUserDynamicCommands private readonly WatchLaterVM m_watchLaterVm; private int m_page = 1; private string m_offset = null; + private string m_baseline = null; #endregion @@ -263,6 +264,33 @@ private void HandleDynamicResults(DynAllReply results) } } + private void HandleDynamicSeasonResults(DynVideoReply results) + { + CanLoadMore = false; + var seasonItems = m_mapper.Map>(results.VideoFollowList.List.ToList()); + var dynamicItems = seasonItems.Select(x => x.ToDynamicItem()).ToList(); + DynamicItems = new ObservableCollection(dynamicItems); + } + + private void HandleDynamicVideoResults(DynVideoReply results) + { + CanLoadMore = results.DynamicList.HasMore; + m_offset = results.DynamicList.HistoryOffset; + m_baseline = results.DynamicList.UpdateBaseline; + var items = m_mapper.Map>(results.DynamicList.List.ToList()); + + foreach (var item in items) + { + item.Parent = this; + } + if (m_page == 1) + DynamicItems = new ObservableCollection(items); + else + { + DynamicItems.AddRange(items); + } + } + #endregion #region Public Methods @@ -281,7 +309,7 @@ public async void LoadMore() await GetDynamicItems(m_page + 1); } - public async Task GetDynamicItems(int page = 1) + public async Task GetDynamicItems(int page = 1, UserDynamicShowType showType = UserDynamicShowType.All) { try { @@ -291,9 +319,33 @@ public async Task GetDynamicItems(int page = 1) if (page == 1) { m_offset = null; + DynamicItems?.Clear(); + } + + switch (showType) + { + case UserDynamicShowType.All: + { + var results = await m_grpcService.GetDynAll(page: page, offset: m_offset); + HandleDynamicResults(results); + break; + } + case UserDynamicShowType.Video: + { + var results = await m_grpcService.GetDynVideo(page, m_offset, m_baseline); + HandleDynamicVideoResults(results); + break; + } + case UserDynamicShowType.Season: + { + var results = await m_grpcService.GetDynVideo(page, m_offset, m_baseline); + HandleDynamicSeasonResults(results); + break; + } + case UserDynamicShowType.Article: + throw new NotImplementedException(); + break; } - var results = await m_grpcService.GetDynAll(page: page, offset: m_offset); - HandleDynamicResults(results); } catch (CustomizedErrorException ex) { From 4fc3f2f73a87ec99457120bef2d11821ade6be73 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Thu, 18 Apr 2024 21:13:23 +0800 Subject: [PATCH 10/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E8=AF=84=E8=AE=BA=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pages/Home/UserDynamicAllPage.xaml | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml index e35991bc..1c43eb10 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml @@ -154,22 +154,22 @@ - - - - - + + + + + From d5f812929b2bd9a6ae982f4ac8134d54cca071ac Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sat, 20 Apr 2024 11:48:11 +0800 Subject: [PATCH 11/30] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E4=B8=93=E6=A0=8F?= =?UTF-8?q?=E5=8A=A8=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/BiliLite.UWP.csproj | 2 + .../UserDynamicItemV2DataTemplateSelector.cs | 3 + .../Dynamic/DynamicItemV2Control.xaml | 75 ++++++++-------- .../Controls/Dynamic/DynamicV2Template.xaml | 34 +++++++- src/BiliLite.UWP/Models/Common/Constants.cs | 2 + .../Common/UserDynamic/NavDynArticle.cs | 87 +++++++++++++++++++ .../Common/UserDynamic/NavDynArticles.cs | 18 ++++ .../Models/Requests/Api/User/DynamicAPI.cs | 14 +++ .../UserDynamic/DynamicV2ItemViewModel.cs | 2 + .../UserDynamic/UserDynamicAllViewModel.cs | 37 +++++++- 10 files changed, 236 insertions(+), 38 deletions(-) create mode 100644 src/BiliLite.UWP/Models/Common/UserDynamic/NavDynArticle.cs create mode 100644 src/BiliLite.UWP/Models/Common/UserDynamic/NavDynArticles.cs diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj index 49bb98d1..e2788a49 100644 --- a/src/BiliLite.UWP/BiliLite.UWP.csproj +++ b/src/BiliLite.UWP/BiliLite.UWP.csproj @@ -159,6 +159,8 @@ + + diff --git a/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs index 56b20bc4..42d64a4f 100644 --- a/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs +++ b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs @@ -39,6 +39,7 @@ DataTemplate SelectRowTemplate(UserDynamicItemDataTemplateSelector selector, { Constants.DynamicTypes.COMMON_SQUARE, (selector, model) => selector.CommonSquareTemplate }, { Constants.DynamicTypes.LIVE_RCMD, (selector, model) => selector.LiveRcmdTemplate }, { Constants.DynamicTypes.CUSTOM_SEASON, (selector, model) => selector.CustomSeasonTemplate }, + { Constants.DynamicTypes.CUSTOM_ARTICLE, (selector, model) => selector.CustomArticleTemplate }, }; } @@ -66,6 +67,8 @@ DataTemplate SelectRowTemplate(UserDynamicItemDataTemplateSelector selector, public DataTemplate CustomSeasonTemplate { get; set; } + public DataTemplate CustomArticleTemplate { get; set; } + public DataTemplate OtherTemplate { get; set; } protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml index 80e0ca66..79695504 100644 --- a/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml @@ -124,58 +124,61 @@ Content="{x:Bind Path=ViewModel.Content,Mode=OneWay}"> - + + - - - - - + - + - + + + + diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml index d6021e7f..bc7f9a8f 100644 --- a/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml @@ -17,7 +17,8 @@ Draw3x3Template="{StaticResource DynamicDraw3x3}" CommonSquareTemplate="{StaticResource DynamicCommonSquare}" LiveRcmdTemplate="{StaticResource DynamicLiveRcmd}" - CustomSeasonTemplate="{StaticResource DynamicCustomSeason}"> + CustomSeasonTemplate="{StaticResource DynamicCustomSeason}" + CustomArticleTemplate="{StaticResource DynamicCustomArticle}"> @@ -383,6 +384,37 @@ + + + + + + + + + + diff --git a/src/BiliLite.UWP/Models/Common/Constants.cs b/src/BiliLite.UWP/Models/Common/Constants.cs index 2ed2ab0f..e6d60d43 100644 --- a/src/BiliLite.UWP/Models/Common/Constants.cs +++ b/src/BiliLite.UWP/Models/Common/Constants.cs @@ -103,6 +103,8 @@ public static class DynamicTypes public const string LIVE_RCMD = "LiveRcmd"; public const string CUSTOM_SEASON = "CustomSeason"; + + public const string CUSTOM_ARTICLE = "CustomArticle"; } } } diff --git a/src/BiliLite.UWP/Models/Common/UserDynamic/NavDynArticle.cs b/src/BiliLite.UWP/Models/Common/UserDynamic/NavDynArticle.cs new file mode 100644 index 00000000..d0ec07a8 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/UserDynamic/NavDynArticle.cs @@ -0,0 +1,87 @@ +using Bilibili.App.Dynamic.V2; +using BiliLite.ViewModels.UserDynamic; +using Newtonsoft.Json; + +namespace BiliLite.Models.Common.UserDynamic +{ + public class NavDynArticle + { + public string Cover { get; set; } + + [JsonProperty("id_str")] + public string Id { get; set; } + + [JsonProperty("jump_url")] + public string JumpUrl { get; set; } + + [JsonProperty("pub_time")] + public string PubTime { get; set; } + + public long Rid { get; set; } + + public string Title { get; set; } + + public bool Visible { get; set; } + + public NavDynArticleAuthor Author { get; set; } + + public DynamicV2ItemViewModel ToDynamicItem() + { + var item = new DynamicV2ItemViewModel() + { + CardType = Constants.DynamicTypes.CUSTOM_ARTICLE, + CustomArticle = this, + Author = new ModuleAuthor() + { + Mid = Author.Mid, + Author = new UserInfo() + { + Face = Author.Face, + Official = new OfficialVerify() + { + Type = Author.Official.Type + }, + Name = Author.Name, + Vip = new VipInfo() + { + Status = Author.Vip.Status + }, + }, + PtimeLabelText = PubTime, + }, + Extend = new Extend() + { + DynIdStr = Id + } + }; + return item; + } + } + + public class NavDynArticleAuthor + { + public string Face { get; set; } + + public long Mid { get; set; } + + public string Name { get; set; } + + public NavDynArticleAuthorOfficial Official { get; set; } + + public NavDynArticleAuthorVip Vip { get; set; } + } + + public class NavDynArticleAuthorOfficial + { + public int Role { get; set; } + + public int Type { get; set; } + + public string Title { get; set; } + } + + public class NavDynArticleAuthorVip + { + public int Status { get; set; } + } +} diff --git a/src/BiliLite.UWP/Models/Common/UserDynamic/NavDynArticles.cs b/src/BiliLite.UWP/Models/Common/UserDynamic/NavDynArticles.cs new file mode 100644 index 00000000..8c337148 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/UserDynamic/NavDynArticles.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace BiliLite.Models.Common.UserDynamic +{ + public class NavDynArticles + { + [JsonProperty("has_more")] + public bool HasMore { get; set; } + + public List Items { get; set; } + + public string Offset { get; set; } + + [JsonProperty("update_baseline")] + public string UpdateBaseline { 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 f0dfc5fa..d8e03522 100644 --- a/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs +++ b/src/BiliLite.UWP/Models/Requests/Api/User/DynamicAPI.cs @@ -157,6 +157,20 @@ public ApiModel SpaceHistoryV2(string mid, string offset = "") return api; } + + public ApiModel Article(string updateBaseline,string type="article") + { + var api = new ApiModel() + { + method = RestSharp.Method.Get, + baseUrl = $"https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/nav", + parameter = $"type={type}&update_baseline={updateBaseline}", + need_cookie = true, + }; + + return api; + } + /// /// 推荐话题 /// diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs index 7f95a517..f1e34981 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs @@ -37,6 +37,8 @@ public DynamicV2ItemViewModel() public UserDynamicSeasonInfo Season { get; set; } + public NavDynArticle CustomArticle { get; set; } + public ModuleDynamic Dynamic { get diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs index b6675240..20653db6 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs @@ -291,6 +291,38 @@ private void HandleDynamicVideoResults(DynVideoReply results) } } + private async Task GetDynArticle() + { + if (m_offset == null) + { + m_baseline = "0"; + } + var api = m_dynamicApi.Article(m_baseline); + var results = await api.Request(); + if (!results.status) + { + throw new CustomizedErrorException(results.message); + } + + var data = await results.GetData(); + + if (!data.success) + { + throw new CustomizedErrorException(data.message); + } + + return data.data; + } + + private void HandleDynamicArticleResults(NavDynArticles results) + { + CanLoadMore = results.HasMore; + m_offset = results.Offset; + m_baseline = results.UpdateBaseline; + var dynamicItems = results.Items.Select(x => x.ToDynamicItem()).ToList(); + DynamicItems = new ObservableCollection(dynamicItems); + } + #endregion #region Public Methods @@ -343,8 +375,11 @@ public async Task GetDynamicItems(int page = 1, UserDynamicShowType showType = U break; } case UserDynamicShowType.Article: - throw new NotImplementedException(); + { + var results = await GetDynArticle(); + HandleDynamicArticleResults(results); break; + } } } catch (CustomizedErrorException ex) From b3c60b9f00ed0cdb85f9e706f6ecc0d45b79532a Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sat, 20 Apr 2024 11:59:43 +0800 Subject: [PATCH 12/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=8D=E5=88=B6?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/Extensions/MapperExtensions.cs | 5 ++++- .../ViewModels/UserDynamic/DynamicV2ItemViewModel.cs | 2 ++ .../ViewModels/UserDynamic/UserDynamicAllViewModel.cs | 2 +- .../ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/BiliLite.UWP/Extensions/MapperExtensions.cs b/src/BiliLite.UWP/Extensions/MapperExtensions.cs index 239a4867..ff03b406 100644 --- a/src/BiliLite.UWP/Extensions/MapperExtensions.cs +++ b/src/BiliLite.UWP/Extensions/MapperExtensions.cs @@ -144,7 +144,10 @@ public static IServiceCollection AddMapper(this IServiceCollection services) src.Modules.FirstOrDefault(x => x.ModuleType == DynModuleType.ModuleOpusSummary).ModuleOpusSummary)) .ForMember(dest => dest.Stat, opt => opt.MapFrom(src => - src.Modules.FirstOrDefault(x => x.ModuleType == DynModuleType.ModuleStat).ModuleStat)); + src.Modules.FirstOrDefault(x => x.ModuleType == DynModuleType.ModuleStat).ModuleStat)) + .ForMember(dest => dest.SourceJson, + opt => opt.MapFrom(src => + src.ToString())); expression.CreateMap(); expression.CreateMap(); diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs index f1e34981..78554c2f 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs @@ -39,6 +39,8 @@ public DynamicV2ItemViewModel() public NavDynArticle CustomArticle { get; set; } + public string SourceJson { get; set; } + public ModuleDynamic Dynamic { get diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs index 20653db6..8243c16e 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs @@ -243,7 +243,7 @@ private async void OpenSendDynamicDialog(DynamicV2ItemViewModel data) private void CopyDyn(DynamicV2ItemViewModel data) { - var dataStr = JsonConvert.SerializeObject(data); + var dataStr = data.SourceJson; Notify.ShowMessageToast(dataStr.SetClipboard() ? "已复制" : "复制失败"); } diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs index 8a4e15f0..642fa780 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs @@ -261,7 +261,7 @@ private async void OpenSendDynamicDialog(DynamicV2ItemViewModel data) private void CopyDyn(DynamicV2ItemViewModel data) { - var dataStr = JsonConvert.SerializeObject(data); + var dataStr = data.SourceJson; Notify.ShowMessageToast(dataStr.SetClipboard() ? "已复制" : "复制失败"); } From 71986871f1aed444565359b800b493d3bc063de3 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sat, 20 Apr 2024 12:18:23 +0800 Subject: [PATCH 13/30] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E5=90=88=E9=9B=86?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E6=98=BE=E7=A4=BA=EF=BC=8C=E5=B1=8F=E8=94=BD?= =?UTF-8?q?Banner=E5=8A=A8=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserDynamicItemV2DataTemplateSelector.cs | 3 ++ .../Controls/Dynamic/DynamicV2Template.xaml | 30 +++++++++++++++++++ src/BiliLite.UWP/Models/Common/Constants.cs | 4 +++ .../UserDynamic/DynamicV2ItemViewModel.cs | 3 +- .../UserDynamic/UserDynamicAllViewModel.cs | 5 ++-- 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs index 42d64a4f..16f266df 100644 --- a/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs +++ b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs @@ -40,6 +40,7 @@ DataTemplate SelectRowTemplate(UserDynamicItemDataTemplateSelector selector, { Constants.DynamicTypes.LIVE_RCMD, (selector, model) => selector.LiveRcmdTemplate }, { Constants.DynamicTypes.CUSTOM_SEASON, (selector, model) => selector.CustomSeasonTemplate }, { Constants.DynamicTypes.CUSTOM_ARTICLE, (selector, model) => selector.CustomArticleTemplate }, + { Constants.DynamicTypes.UGC_SEASON, (selector, model) => selector.UgcSeasonTemplate }, }; } @@ -65,6 +66,8 @@ DataTemplate SelectRowTemplate(UserDynamicItemDataTemplateSelector selector, public DataTemplate LiveRcmdTemplate { get; set; } + public DataTemplate UgcSeasonTemplate { get; set; } + public DataTemplate CustomSeasonTemplate { get; set; } public DataTemplate CustomArticleTemplate { get; set; } diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml index bc7f9a8f..182e0746 100644 --- a/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml @@ -17,6 +17,7 @@ Draw3x3Template="{StaticResource DynamicDraw3x3}" CommonSquareTemplate="{StaticResource DynamicCommonSquare}" LiveRcmdTemplate="{StaticResource DynamicLiveRcmd}" + UgcSeasonTemplate="{StaticResource DynamicUgcSeason}" CustomSeasonTemplate="{StaticResource DynamicCustomSeason}" CustomArticleTemplate="{StaticResource DynamicCustomArticle}"> @@ -213,6 +214,35 @@ + + + + + + + + diff --git a/src/BiliLite.UWP/Models/Common/Constants.cs b/src/BiliLite.UWP/Models/Common/Constants.cs index e6d60d43..5363d086 100644 --- a/src/BiliLite.UWP/Models/Common/Constants.cs +++ b/src/BiliLite.UWP/Models/Common/Constants.cs @@ -102,6 +102,10 @@ public static class DynamicTypes public const string LIVE_RCMD = "LiveRcmd"; + public const string UGC_SEASON = "UgcSeason"; + + public const string BANNER = "Banner"; + public const string CUSTOM_SEASON = "CustomSeason"; public const string CUSTOM_ARTICLE = "CustomArticle"; diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs index 78554c2f..ca187bb2 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs @@ -178,7 +178,8 @@ public string Verify { get { - if (Author == null) return Constants.App.TRANSPARENT_IMAGE; + if (Author?.Author?.Official == null) + return Constants.App.TRANSPARENT_IMAGE; return Author.Author.Official.Type switch { 1 => Constants.App.VERIFY_OGANIZATION_IMAGE, diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs index 8243c16e..54ef3c38 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs @@ -21,7 +21,7 @@ using BiliLite.Pages; using BiliLite.Pages.User; using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; +using DynamicType = Bilibili.App.Dynamic.V2.DynamicType; namespace BiliLite.ViewModels.UserDynamic { @@ -251,7 +251,8 @@ private void HandleDynamicResults(DynAllReply results) { CanLoadMore = results.DynamicList.HasMore; m_offset = results.DynamicList.HistoryOffset; - var items = m_mapper.Map>(results.DynamicList.List.ToList()); + var items = m_mapper.Map>(results.DynamicList.List + .Where(x => x.CardType != DynamicType.Banner).ToList()); foreach (var item in items) { item.Parent = this; From eebf5458f3008cb7f272ba0a24509cc887feb740 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sat, 20 Apr 2024 12:30:09 +0800 Subject: [PATCH 14/30] =?UTF-8?q?=E5=88=86=E7=A6=BB=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E8=AF=84=E8=AE=BA=E5=AE=BD=E5=BA=A6=E8=AE=BE=E7=BD=AE=E5=92=8C?= =?UTF-8?q?=E8=A7=86=E9=A2=91=E8=AF=A6=E6=83=85=E5=AE=BD=E5=BA=A6=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/Models/Common/SettingConstants.cs | 6 ++++++ src/BiliLite.UWP/Pages/SettingPage.xaml | 6 ++++++ src/BiliLite.UWP/Pages/SettingPage.xaml.cs | 10 ++++++++++ .../ViewModels/UserDynamic/UserDynamicAllViewModel.cs | 8 +------- .../UserDynamic/UserDynamicSpaceViewModel.cs | 8 +------- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/BiliLite.UWP/Models/Common/SettingConstants.cs b/src/BiliLite.UWP/Models/Common/SettingConstants.cs index bff7547e..fd82144e 100644 --- a/src/BiliLite.UWP/Models/Common/SettingConstants.cs +++ b/src/BiliLite.UWP/Models/Common/SettingConstants.cs @@ -56,6 +56,12 @@ public class UI [SettingKey(typeof(bool))] public const string RIGHT_WIDTH_CHANGEABLE = "PlayerRightDetailWidthChangeable"; + [SettingKey(typeof(double))] + public const string DYNAMIC_COMMENT_WIDTH = "DynamicCommentWidth"; + + [SettingDefaultValue] + public const double DEFAULT_DYNAMIC_COMMENT_WIDTH = 480; + /// /// 图片圆角半径 /// diff --git a/src/BiliLite.UWP/Pages/SettingPage.xaml b/src/BiliLite.UWP/Pages/SettingPage.xaml index 73ff8c3d..7aeddf26 100644 --- a/src/BiliLite.UWP/Pages/SettingPage.xaml +++ b/src/BiliLite.UWP/Pages/SettingPage.xaml @@ -153,6 +153,12 @@ + + 动态 + 动态评论宽度(下次打开应用生效) + + + 图片圆角半径(重启生效) diff --git a/src/BiliLite.UWP/Pages/SettingPage.xaml.cs b/src/BiliLite.UWP/Pages/SettingPage.xaml.cs index 51e281e9..ce97db6d 100644 --- a/src/BiliLite.UWP/Pages/SettingPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/SettingPage.xaml.cs @@ -161,6 +161,16 @@ private void LoadUI() }); }); + //动态评论宽度 + NumBoxDynamicCommentWidth.Value = SettingService.GetValue(SettingConstants.UI.DYNAMIC_COMMENT_WIDTH, SettingConstants.UI.DEFAULT_DYNAMIC_COMMENT_WIDTH); + NumBoxDynamicCommentWidth.Loaded += (sender, e) => + { + NumBoxDynamicCommentWidth.ValueChanged += (obj, args) => + { + SettingService.SetValue(SettingConstants.UI.DYNAMIC_COMMENT_WIDTH, args.NewValue); + }; + }; + //图片圆角半径 numImageCornerRadius.Value = SettingService.GetValue(SettingConstants.UI.IMAGE_CORNER_RADIUS, 0); ImageCornerRadiusExample.CornerRadius = new CornerRadius(numImageCornerRadius.Value); diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs index 54ef3c38..17f8b6c4 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs @@ -96,13 +96,7 @@ public UserDynamicAllViewModel(GrpcService grpcService, IMapper mapper) public ObservableCollection DynamicItems { get; set; } - public int CommentControlWidth - { - get - { - return SettingService.GetValue(SettingConstants.UI.RIGHT_DETAIL_WIDTH, 320); - } - } + public double CommentControlWidth => SettingService.GetValue(SettingConstants.UI.DYNAMIC_COMMENT_WIDTH, SettingConstants.UI.DEFAULT_DYNAMIC_COMMENT_WIDTH); #endregion diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs index 642fa780..19a2f2f3 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicSpaceViewModel.cs @@ -97,13 +97,7 @@ public UserDynamicSpaceViewModel(GrpcService grpcService, IMapper mapper) public ObservableCollection DynamicItems { get; set; } - public int CommentControlWidth - { - get - { - return SettingService.GetValue(SettingConstants.UI.RIGHT_DETAIL_WIDTH, 320); - } - } + public double CommentControlWidth => SettingService.GetValue(SettingConstants.UI.DYNAMIC_COMMENT_WIDTH, SettingConstants.UI.DEFAULT_DYNAMIC_COMMENT_WIDTH); #endregion From d22b36a15ba1a2d2f1d09581d2ecff26814c6895 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sat, 20 Apr 2024 15:11:10 +0800 Subject: [PATCH 15/30] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E8=AF=84=E8=AE=BA=E6=98=BE=E7=A4=BA=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pages/Home/UserDynamicAllPage.xaml | 77 ++++++++++++++----- .../Pages/Home/UserDynamicAllPage.xaml.cs | 1 - .../Pages/User/DynamicSpacePage.xaml | 77 ++++++++++++++----- 3 files changed, 112 insertions(+), 43 deletions(-) diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml index 1c43eb10..ad80b56e 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml @@ -31,44 +31,74 @@ - - - - - - + - + + + Collapsed + + + Visible - + + + Collapsed + + + Visible + + - - - - + - - + + + + + + + + - + + + Visible + + + Collapsed - + + + Visible + + + Collapsed + + + + + + + + + + @@ -159,16 +189,21 @@ Visibility="Collapsed" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - Background="{ThemeResource HalfTransparentBackground}"> - + - + + VerticalAlignment="Stretch" RenderTransformOrigin="0.5,0.5"> + + + diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs index 46f524cd..be302f76 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs @@ -121,7 +121,6 @@ private void CloseCommentCore() storyboard.Begin(); } - private void UserDynamicViewModelOpenCommentEvent(object sender, DynamicV2ItemViewModel e) { CommentApi.CommentType commentType = CommentApi.CommentType.Dynamic; diff --git a/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml b/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml index 8ba235e1..691291fc 100644 --- a/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml +++ b/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml @@ -26,44 +26,74 @@ - - - - - - + - + + + Collapsed + + + Visible - + + + Collapsed + + + Visible + + - - - - + - - + + + + + + + + - + + + Visible + + + Collapsed - + + + Visible + + + Collapsed + + + + + + + + + + @@ -106,16 +136,21 @@ Visibility="Collapsed" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - Background="{ThemeResource HalfTransparentBackground}"> - + - + + VerticalAlignment="Stretch" RenderTransformOrigin="0.5,0.5"> + + + From c2ed8b775554551f107d5966032e780eaf5b74f1 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sat, 20 Apr 2024 16:06:39 +0800 Subject: [PATCH 16/30] =?UTF-8?q?=E5=8A=A8=E6=80=81=E9=A1=B5TopBar?= =?UTF-8?q?=E5=AE=BD=E5=BA=A6=E9=9A=8F=E8=A7=86=E5=9B=BE=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=8F=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml | 8 ++++---- .../Pages/Home/UserDynamicAllPage.xaml.cs | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml index ad80b56e..6227087b 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml @@ -102,16 +102,16 @@ - + - + - - + + diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs index be302f76..b601ff54 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs @@ -73,6 +73,12 @@ private void SetGridCore() BtnList.Visibility = Visibility.Visible; //XAML ListDyn.ItemsPanel = (ItemsPanelTemplate)this.Resources["GridPanel"]; + + //顶部 + GridTopBar.MaxWidth = double.MaxValue; + GridTopBar.Margin = new Thickness(0, 0, 0, 4); + BorderTopBar.CornerRadius = new CornerRadius(0); + BorderTopBar.Margin = new Thickness(0); } private void SetListCore() @@ -83,6 +89,12 @@ private void SetListCore() BtnList.Visibility = Visibility.Collapsed; //XAML ListDyn.ItemsPanel = (ItemsPanelTemplate)this.Resources["ListPanel"]; + + //顶部 + GridTopBar.MaxWidth = 800; + GridTopBar.Margin = new Thickness(8, 0, 8, 0); + BorderTopBar.CornerRadius = new CornerRadius(4); + BorderTopBar.Margin = new Thickness(12, 4, 12, 4); } private async void BtnRefreshDynamic_OnClick(object sender, RoutedEventArgs e) From e46266edd0243becf06900003ae5e268c613ade1 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Mon, 22 Apr 2024 22:21:13 +0800 Subject: [PATCH 17/30] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=BF=AB=E6=8D=B7?= =?UTF-8?q?=E9=94=AE=E5=88=B7=E6=96=B0=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/BiliLite.UWP.csproj | 5 ++ src/BiliLite.UWP/MainPage.xaml.cs | 27 ++++++++++- .../Models/Functions/IShortcutFunction.cs | 11 +++++ .../Functions/RefreshShortcutFunction.cs | 16 +++++++ src/BiliLite.UWP/NoTabMainPage.xaml.cs | 20 +++++++- src/BiliLite.UWP/Pages/DownloadPage.xaml.cs | 19 ++++---- src/BiliLite.UWP/Pages/Home/AnimePage.xaml.cs | 9 +++- .../Pages/Home/DynamicPage.xaml.cs | 12 +++-- src/BiliLite.UWP/Pages/Home/HotPage.xaml.cs | 7 ++- src/BiliLite.UWP/Pages/Home/LivePage.xaml.cs | 9 +++- src/BiliLite.UWP/Pages/Home/MoviePage.xaml.cs | 19 +++----- .../Pages/Home/RecommendPage.xaml.cs | 13 +++++- .../Pages/Home/UserDynamicAllPage.xaml.cs | 10 +++- src/BiliLite.UWP/Pages/HomePage.xaml.cs | 12 ++++- src/BiliLite.UWP/Pages/IMainPage.cs | 7 +++ src/BiliLite.UWP/Pages/IRefreshablePage.cs | 9 ++++ .../Pages/Live/LiveAreaDetailPage.xaml.cs | 21 ++++----- .../Pages/Live/LiveCenterPage.xaml.cs | 19 +++----- .../Pages/Live/LiveRecommendPage.xaml.cs | 30 ++++++------ .../Pages/RegionDetailPage.xaml.cs | 23 +++++----- src/BiliLite.UWP/Pages/SearchPage.xaml.cs | 11 ++++- .../Pages/User/DynamicSpacePage.xaml.cs | 10 +++- .../Pages/User/FavoriteDetailPage.xaml.cs | 8 +++- .../Pages/User/FavoritePage.xaml.cs | 18 ++++---- .../Pages/User/HistoryPage.xaml.cs | 10 +++- .../Pages/User/WatchlaterPage.xaml.cs | 19 +++----- src/BiliLite.UWP/Pages/UserInfoPage.xaml.cs | 10 +++- .../Pages/VideoDetailPage.xaml.cs | 9 +++- .../Services/ShortcutKeyService.cs | 46 +++++++++++++++++++ src/BiliLite.UWP/Startup.cs | 1 + 30 files changed, 317 insertions(+), 123 deletions(-) create mode 100644 src/BiliLite.UWP/Models/Functions/IShortcutFunction.cs create mode 100644 src/BiliLite.UWP/Models/Functions/RefreshShortcutFunction.cs create mode 100644 src/BiliLite.UWP/Pages/IMainPage.cs create mode 100644 src/BiliLite.UWP/Pages/IRefreshablePage.cs create mode 100644 src/BiliLite.UWP/Services/ShortcutKeyService.cs diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj index e2788a49..bc64e636 100644 --- a/src/BiliLite.UWP/BiliLite.UWP.csproj +++ b/src/BiliLite.UWP/BiliLite.UWP.csproj @@ -167,10 +167,15 @@ + + UserDynamicAllPage.xaml + + + diff --git a/src/BiliLite.UWP/MainPage.xaml.cs b/src/BiliLite.UWP/MainPage.xaml.cs index 6a47ea94..dd3df3df 100644 --- a/src/BiliLite.UWP/MainPage.xaml.cs +++ b/src/BiliLite.UWP/MainPage.xaml.cs @@ -12,6 +12,7 @@ using BiliLite.Models.Common; using BiliLite.Extensions; using BiliLite.Services; +using Microsoft.Extensions.DependencyInjection; // https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x804 上介绍了“空白页”项模板 @@ -20,12 +21,15 @@ namespace BiliLite /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class MainPage : Windows.UI.Xaml.Controls.Page + public sealed partial class MainPage : Windows.UI.Xaml.Controls.Page, IMainPage { private static readonly ILogger _logger = GlobalLogger.FromCurrentType(); + private readonly ShortcutKeyService m_shortcutKeyService; public MainPage() { + m_shortcutKeyService = App.ServiceProvider.GetRequiredService(); + m_shortcutKeyService.SetMainPage(this); this.InitializeComponent(); // 处理标题栏 var coreTitleBar = CoreApplication.GetCurrentView().TitleBar; @@ -42,6 +46,26 @@ public MainPage() App.Current.Suspending += Current_Suspending; // Window.Current.Content.PointerPressed += Content_PointerPressed; + + Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated; + } + + public object CurrentPage + { + get + { + if (!(tabView.SelectedItem is TabViewItem tabItem)) return null; + if (!(tabItem.Content is Frame frame)) return null; + return frame.Content; + } + } + + private void Dispatcher_AcceleratorKeyActivated(Windows.UI.Core.CoreDispatcher sender, Windows.UI.Core.AcceleratorKeyEventArgs args) + { + if (args.EventType.ToString().Contains("Down")) + { + m_shortcutKeyService.HandleKeyDown(args.VirtualKey); + } } private async void Current_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e) @@ -259,7 +283,6 @@ private void CloseSelectedTabKeyboardAccelerator_Invoked(KeyboardAccelerator sen ClosePage((TabViewItem)tabView.SelectedItem); } args.Handled = true; - } private void tabView_TabItemsChanged(TabView sender, IVectorChangedEventArgs args) diff --git a/src/BiliLite.UWP/Models/Functions/IShortcutFunction.cs b/src/BiliLite.UWP/Models/Functions/IShortcutFunction.cs new file mode 100644 index 00000000..bcba2d7a --- /dev/null +++ b/src/BiliLite.UWP/Models/Functions/IShortcutFunction.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace BiliLite.Models.Functions +{ + public interface IShortcutFunction + { + public string Name { get; } + + public Task Action(object param); + } +} diff --git a/src/BiliLite.UWP/Models/Functions/RefreshShortcutFunction.cs b/src/BiliLite.UWP/Models/Functions/RefreshShortcutFunction.cs new file mode 100644 index 00000000..d4b14234 --- /dev/null +++ b/src/BiliLite.UWP/Models/Functions/RefreshShortcutFunction.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; +using BiliLite.Pages; + +namespace BiliLite.Models.Functions +{ + public class RefreshShortcutFunction : IShortcutFunction + { + public string Name { get; } = "刷新"; + + public async Task Action(object param) + { + if (!(param is IRefreshablePage page)) return; + await page.Refresh(); + } + } +} diff --git a/src/BiliLite.UWP/NoTabMainPage.xaml.cs b/src/BiliLite.UWP/NoTabMainPage.xaml.cs index 397aa470..8db9dc75 100644 --- a/src/BiliLite.UWP/NoTabMainPage.xaml.cs +++ b/src/BiliLite.UWP/NoTabMainPage.xaml.cs @@ -3,6 +3,7 @@ using BiliLite.Models.Common; using BiliLite.Pages; using BiliLite.Services; +using Microsoft.Extensions.DependencyInjection; using System; using System.Linq; using Windows.ApplicationModel.Core; @@ -20,10 +21,14 @@ namespace BiliLite /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class NoTabMainPage : Page + public sealed partial class NoTabMainPage : Page, IMainPage { + private readonly ShortcutKeyService m_shortcutKeyService; + public NoTabMainPage() { + m_shortcutKeyService = App.ServiceProvider.GetRequiredService(); + m_shortcutKeyService.SetMainPage(this); this.InitializeComponent(); var coreTitleBar = CoreApplication.GetCurrentView().TitleBar; mode = SettingService.GetValue(SettingConstants.UI.DISPLAY_MODE, 0); @@ -34,7 +39,20 @@ public NoTabMainPage() MessageCenter.ViewImageEvent += MessageCenter_ViewImageEvent; MessageCenter.MiniWindowEvent += MessageCenter_MiniWindowEvent; Window.Current.Content.PointerPressed += Content_PointerPressed; + + Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated; } + + public object CurrentPage => frame.Content; + + private void Dispatcher_AcceleratorKeyActivated(Windows.UI.Core.CoreDispatcher sender, Windows.UI.Core.AcceleratorKeyEventArgs args) + { + if (args.EventType.ToString().Contains("Down")) + { + m_shortcutKeyService.HandleKeyDown(args.VirtualKey); + } + } + private void MessageCenter_MiniWindowEvent(object sender, bool e) { if (e) diff --git a/src/BiliLite.UWP/Pages/DownloadPage.xaml.cs b/src/BiliLite.UWP/Pages/DownloadPage.xaml.cs index 14d91801..a1478c93 100644 --- a/src/BiliLite.UWP/Pages/DownloadPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/DownloadPage.xaml.cs @@ -1,19 +1,12 @@ -using BiliLite.Modules; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; +using System.Threading.Tasks; using Windows.Storage; using Windows.System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; using BiliLite.Extensions; using BiliLite.Services; @@ -31,7 +24,7 @@ namespace BiliLite.Pages /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class DownloadPage : BasePage + public sealed partial class DownloadPage : BasePage, IRefreshablePage { private static readonly ILogger logger = GlobalLogger.FromCurrentType(); private readonly DownloadPageViewModel m_viewModel; @@ -50,6 +43,12 @@ protected override void OnNavigatedTo(NavigationEventArgs e) m_viewModel.RefreshDownloaded(); } } + + public async Task Refresh() + { + m_viewModel.RefreshDownloaded(); + } + private void listDowned_ItemClick(object sender, ItemClickEventArgs e) { var data = e.ClickedItem as DownloadedItem; diff --git a/src/BiliLite.UWP/Pages/Home/AnimePage.xaml.cs b/src/BiliLite.UWP/Pages/Home/AnimePage.xaml.cs index c8c33fc8..2b4c6cbb 100644 --- a/src/BiliLite.UWP/Pages/Home/AnimePage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/AnimePage.xaml.cs @@ -19,7 +19,7 @@ namespace BiliLite.Pages.Home /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class AnimePage : Page + public sealed partial class AnimePage : Page, IRefreshablePage { private AnimeType animeType; public AnimePageViewModel m_viewModel { get; set; } @@ -100,11 +100,16 @@ private void btnTimeline_Click(object sender, RoutedEventArgs e) }); } - private async void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) + public async Task Refresh() { await LoadData(); } + private async void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) + { + await Refresh(); + } + private async void BannerItem_Click(object sender, RoutedEventArgs e) { var result = await MessageCenter.HandelUrl(((sender as HyperlinkButton).DataContext as AnimeBannerModel).Url); diff --git a/src/BiliLite.UWP/Pages/Home/DynamicPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/DynamicPage.xaml.cs index a6addb75..15cc4a90 100644 --- a/src/BiliLite.UWP/Pages/Home/DynamicPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/DynamicPage.xaml.cs @@ -1,4 +1,5 @@ -using BiliLite.Extensions; +using System.Threading.Tasks; +using BiliLite.Extensions; using BiliLite.Models.Common; using BiliLite.Services; using Windows.UI.Xaml; @@ -16,7 +17,7 @@ namespace BiliLite.Pages.Home /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class DynamicPage : Page + public sealed partial class DynamicPage : Page, IRefreshablePage { private readonly DynamicPageViewModel m_viewModel; @@ -38,11 +39,16 @@ protected override async void OnNavigatedTo(NavigationEventArgs e) } } - private void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) + public async Task Refresh() { m_viewModel.Refresh(); } + private async void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) + { + await Refresh(); + } + private void AdaptiveGridView_ItemClick(object sender, ItemClickEventArgs e) { var item = e.ClickedItem as DynamicItemModel; diff --git a/src/BiliLite.UWP/Pages/Home/HotPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/HotPage.xaml.cs index d8c16b57..42cb53c7 100644 --- a/src/BiliLite.UWP/Pages/Home/HotPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/HotPage.xaml.cs @@ -16,7 +16,7 @@ namespace BiliLite.Pages.Home /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class HotPage : Page + public sealed partial class HotPage : Page, IRefreshablePage { HotVM hotVM; public HotPage() @@ -100,5 +100,10 @@ private void AddToWatchLater_Click(object sender, RoutedEventArgs e) var data = (sender as MenuFlyoutItem).DataContext as HotDataItemModel; WatchLaterVM.Instance.AddToWatchlater(data.Param); } + + public async Task Refresh() + { + hotVM.Refresh(); + } } } diff --git a/src/BiliLite.UWP/Pages/Home/LivePage.xaml.cs b/src/BiliLite.UWP/Pages/Home/LivePage.xaml.cs index f8cb21cb..1cbc0d20 100644 --- a/src/BiliLite.UWP/Pages/Home/LivePage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/LivePage.xaml.cs @@ -18,7 +18,7 @@ namespace BiliLite.Pages.Home /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class LivePage : Page + public sealed partial class LivePage : Page,IRefreshablePage { private Modules.LiveVM liveVM; public LivePage() @@ -53,11 +53,16 @@ private async Task LoadData() } } - private async void btnRefresh_Click(object sender, RoutedEventArgs e) + public async Task Refresh() { await LoadData(); } + private async void btnRefresh_Click(object sender, RoutedEventArgs e) + { + await Refresh(); + } + private async void BannerItem_Click(object sender, RoutedEventArgs e) { var result = await MessageCenter.HandelUrl(((sender as HyperlinkButton).DataContext as LiveHomeBannerModel).link); diff --git a/src/BiliLite.UWP/Pages/Home/MoviePage.xaml.cs b/src/BiliLite.UWP/Pages/Home/MoviePage.xaml.cs index 048d8fe7..3802c375 100644 --- a/src/BiliLite.UWP/Pages/Home/MoviePage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/MoviePage.xaml.cs @@ -4,19 +4,9 @@ using BiliLite.Modules; using BiliLite.Services; using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; -using Windows.Foundation; -using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 @@ -26,7 +16,7 @@ namespace BiliLite.Pages.Home /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class MoviePage : Page + public sealed partial class MoviePage : Page, IRefreshablePage { readonly Modules.CinemaVM cinemaVM; public MoviePage() @@ -95,7 +85,7 @@ private async void gvFall_ItemClick(object sender, ItemClickEventArgs e) } private async void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) { - await LoadData(); + await Refresh(); } private async void BannerItem_Click(object sender, RoutedEventArgs e) @@ -184,5 +174,10 @@ private void GridView_ItemClick(object sender, ItemClickEventArgs e) var item = e.ClickedItem as PageEntranceModel; MessageCenter.NavigateToPage(this, item.NavigationInfo); } + + public async Task Refresh() + { + await LoadData(); + } } } diff --git a/src/BiliLite.UWP/Pages/Home/RecommendPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/RecommendPage.xaml.cs index ea74521e..2981b658 100644 --- a/src/BiliLite.UWP/Pages/Home/RecommendPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/RecommendPage.xaml.cs @@ -21,7 +21,7 @@ namespace BiliLite.Pages.Home /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class RecommendPage : Page + public sealed partial class RecommendPage : Page, IRefreshablePage { #region Fields @@ -42,6 +42,15 @@ public RecommendPage() #endregion + #region Public Methods + + public async Task Refresh() + { + m_viewModel.Refresh(); + } + + #endregion + #region Protected Methods protected override async void OnNavigatedTo(NavigationEventArgs e) { @@ -87,7 +96,7 @@ private async void RecommendGridView_ItemClick(object sender, ItemClickEventArgs private void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) { - m_viewModel.Refresh(); + Refresh(); } private async void BannerItem_Click(object sender, RoutedEventArgs e) diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs index b601ff54..7d6ce0bf 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Threading.Tasks; using BiliLite.Services; using BiliLite.Models.Common; using BiliLite.Models.Requests.Api; @@ -19,7 +20,7 @@ namespace BiliLite.Pages.Home /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class UserDynamicAllPage : Page + public sealed partial class UserDynamicAllPage : Page,IRefreshablePage { readonly UserDynamicAllViewModel m_viewModel; private bool m_isStaggered = false; @@ -99,7 +100,7 @@ private void SetListCore() private async void BtnRefreshDynamic_OnClick(object sender, RoutedEventArgs e) { - await m_viewModel.GetDynamicItems(showType: m_currentShowType); + await Refresh(); } private void BtnTop_OnClick(object sender, RoutedEventArgs e) @@ -187,5 +188,10 @@ private void CommentPanel_OnTapped(object sender, TappedRoutedEventArgs e) { CloseCommentCore(); } + + public async Task Refresh() + { + await m_viewModel.GetDynamicItems(showType: m_currentShowType); + } } } diff --git a/src/BiliLite.UWP/Pages/HomePage.xaml.cs b/src/BiliLite.UWP/Pages/HomePage.xaml.cs index ee619c6f..ac99a0e8 100644 --- a/src/BiliLite.UWP/Pages/HomePage.xaml.cs +++ b/src/BiliLite.UWP/Pages/HomePage.xaml.cs @@ -4,6 +4,7 @@ using BiliLite.Services; using Microsoft.Toolkit.Uwp.Connectivity; using System; +using System.Threading.Tasks; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; @@ -18,7 +19,7 @@ namespace BiliLite.Pages /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class HomePage : Page + public sealed partial class HomePage : Page, IRefreshablePage { private static readonly ILogger logger = GlobalLogger.FromCurrentType(); @@ -36,6 +37,15 @@ public HomePage() m_downloadPageViewModel = App.ServiceProvider.GetRequiredService(); this.DataContext = m_viewModel; } + + public async Task Refresh() + { + if (frame.Content is IRefreshablePage page) + { + await page.Refresh(); + } + } + private void MessageCenter_LogoutedEvent(object sender, EventArgs e) { LaodUserStatus(); diff --git a/src/BiliLite.UWP/Pages/IMainPage.cs b/src/BiliLite.UWP/Pages/IMainPage.cs new file mode 100644 index 00000000..869a58c8 --- /dev/null +++ b/src/BiliLite.UWP/Pages/IMainPage.cs @@ -0,0 +1,7 @@ +namespace BiliLite.Pages +{ + public interface IMainPage + { + public object CurrentPage { get; } + } +} diff --git a/src/BiliLite.UWP/Pages/IRefreshablePage.cs b/src/BiliLite.UWP/Pages/IRefreshablePage.cs new file mode 100644 index 00000000..b33ec6c6 --- /dev/null +++ b/src/BiliLite.UWP/Pages/IRefreshablePage.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace BiliLite.Pages +{ + public interface IRefreshablePage + { + public Task Refresh(); + } +} diff --git a/src/BiliLite.UWP/Pages/Live/LiveAreaDetailPage.xaml.cs b/src/BiliLite.UWP/Pages/Live/LiveAreaDetailPage.xaml.cs index 22537848..800cf433 100644 --- a/src/BiliLite.UWP/Pages/Live/LiveAreaDetailPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Live/LiveAreaDetailPage.xaml.cs @@ -1,19 +1,11 @@ using BiliLite.Models.Common; using BiliLite.Modules.Live; using BiliLite.Services; -using System; -using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; +using System.Threading.Tasks; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 @@ -28,7 +20,7 @@ public class LiveAreaPar /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class LiveAreaDetailPage : BasePage + public sealed partial class LiveAreaDetailPage : BasePage, IRefreshablePage { LiveAreaDetailVM liveAreaDetailVM; public LiveAreaDetailPage() @@ -48,9 +40,9 @@ protected async override void OnNavigatedTo(NavigationEventArgs e) } } - private void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) + private async void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) { - liveAreaDetailVM.Refresh(); + await Refresh(); } private void AdaptiveGridView_ItemClick(object sender, ItemClickEventArgs e) @@ -75,5 +67,10 @@ private void ToggleButton_Click(object sender, RoutedEventArgs e) liveAreaDetailVM.SelectTag = data; liveAreaDetailVM.Refresh(); } + + public async Task Refresh() + { + liveAreaDetailVM.Refresh(); + } } } diff --git a/src/BiliLite.UWP/Pages/Live/LiveCenterPage.xaml.cs b/src/BiliLite.UWP/Pages/Live/LiveCenterPage.xaml.cs index 7c4658a6..48c53aa4 100644 --- a/src/BiliLite.UWP/Pages/Live/LiveCenterPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Live/LiveCenterPage.xaml.cs @@ -2,18 +2,8 @@ using BiliLite.Modules.Live.LiveCenter; using BiliLite.Services; using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Windows.UI.Xaml; +using System.Threading.Tasks; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 @@ -23,7 +13,7 @@ namespace BiliLite.Pages.Live /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class LiveCenterPage : BasePage + public sealed partial class LiveCenterPage : BasePage, IRefreshablePage { readonly LiveAttentionVM liveAttentionVM; readonly LiveAttentionUnLiveVM liveAttentionUnLiveVM; @@ -97,5 +87,10 @@ private async void pivot_SelectionChanged(object sender, SelectionChangedEventAr await liveCenterHistoryVM.Get(); } } + + public async Task Refresh() + { + throw new NotImplementedException(); + } } } diff --git a/src/BiliLite.UWP/Pages/Live/LiveRecommendPage.xaml.cs b/src/BiliLite.UWP/Pages/Live/LiveRecommendPage.xaml.cs index 768a520f..b7608309 100644 --- a/src/BiliLite.UWP/Pages/Live/LiveRecommendPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Live/LiveRecommendPage.xaml.cs @@ -1,19 +1,10 @@ using BiliLite.Models.Common; using BiliLite.Modules.Live; using BiliLite.Services; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Windows.UI.Xaml; +using System.Threading.Tasks; + using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; + using Windows.UI.Xaml.Navigation; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 @@ -23,7 +14,7 @@ namespace BiliLite.Pages.Live /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class LiveRecommendPage : BasePage + public sealed partial class LiveRecommendPage : BasePage, IRefreshablePage { readonly LiveRecommendVM liveRecommendVM; public LiveRecommendPage() @@ -72,10 +63,17 @@ private void AdaptiveGridView_ItemClick(object sender, ItemClickEventArgs e) }); } - private void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) + private async void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) { - var data = sender.DataContext as LiveRecommendItem; - data.Refresh(); + await Refresh(); + } + + public async Task Refresh() + { + if(pivot.SelectedItem is LiveRecommendItem item) + { + item.Refresh(); + } } } } diff --git a/src/BiliLite.UWP/Pages/RegionDetailPage.xaml.cs b/src/BiliLite.UWP/Pages/RegionDetailPage.xaml.cs index c2cd55a7..a503de10 100644 --- a/src/BiliLite.UWP/Pages/RegionDetailPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/RegionDetailPage.xaml.cs @@ -2,19 +2,9 @@ using BiliLite.Modules; using BiliLite.Pages.Bangumi; using BiliLite.Services; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; +using System.Threading.Tasks; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 @@ -24,7 +14,7 @@ namespace BiliLite.Pages /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class RegionDetailPage : BasePage + public sealed partial class RegionDetailPage : BasePage, IRefreshablePage { RegionDetailVM regionDetailVM; OpenRegionInfo regionInfo; @@ -155,6 +145,15 @@ private void AddToWatchLater_Click(object sender, RoutedEventArgs e) Modules.User.WatchLaterVM.Instance.AddToWatchlater(data.param); } + + public async Task Refresh() + { + if (cbTags.SelectedItem == null) + { + return; + } + (pivot.SelectedItem as RegionDetailChildVM).Refresh(); + } } public class RegionDataTemplateSelector : DataTemplateSelector { diff --git a/src/BiliLite.UWP/Pages/SearchPage.xaml.cs b/src/BiliLite.UWP/Pages/SearchPage.xaml.cs index 3bc486c9..74412c49 100644 --- a/src/BiliLite.UWP/Pages/SearchPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/SearchPage.xaml.cs @@ -1,4 +1,5 @@ -using BiliLite.Extensions; +using System.Threading.Tasks; +using BiliLite.Extensions; using BiliLite.Models.Common; using BiliLite.Modules; using BiliLite.Services; @@ -55,7 +56,7 @@ public class SearchParameter /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class SearchPage : BasePage + public sealed partial class SearchPage : BasePage, IRefreshablePage { SearchVM searchVM; public SearchPage() @@ -271,6 +272,12 @@ private async void txtKeyword_TextChanged(AutoSuggestBox sender, AutoSuggestBoxT searchVM.SuggestSearchContents.ReplaceRange(suggestSearchContents); } } + + public async Task Refresh() + { + if (!(pivot.SelectedItem is ISearchVM searchVm)) return; + searchVm.Refresh(); + } } public class SearchDataTemplateSelector : DataTemplateSelector { diff --git a/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml.cs b/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml.cs index 4a21e0bb..2b231a09 100644 --- a/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml.cs +++ b/src/BiliLite.UWP/Pages/User/DynamicSpacePage.xaml.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Threading.Tasks; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; @@ -18,7 +19,7 @@ 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 + public sealed partial class DynamicSpacePage : Page, IRefreshablePage { private readonly UserDynamicSpaceViewModel m_viewModel; private bool m_isStaggered = false; @@ -75,7 +76,7 @@ protected override async void OnNavigatedTo(NavigationEventArgs e) private async void BtnRefreshDynamic_OnClick(object sender, RoutedEventArgs e) { - await m_viewModel.GetDynamicItems(); + await Refresh(); } private void BtnTop_OnClick(object sender, RoutedEventArgs e) @@ -156,5 +157,10 @@ private void CommentPanel_OnTapped(object sender, TappedRoutedEventArgs e) { CloseCommentCore(); } + + public async Task Refresh() + { + await m_viewModel.GetDynamicItems(); + } } } diff --git a/src/BiliLite.UWP/Pages/User/FavoriteDetailPage.xaml.cs b/src/BiliLite.UWP/Pages/User/FavoriteDetailPage.xaml.cs index 01f9b6a3..23f29a7c 100644 --- a/src/BiliLite.UWP/Pages/User/FavoriteDetailPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/User/FavoriteDetailPage.xaml.cs @@ -5,6 +5,7 @@ using BiliLite.Services; using System; using System.Collections.Generic; +using System.Threading.Tasks; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; @@ -22,7 +23,7 @@ public class FavoriteDetailArgs /// /// 收藏夹详情、播放列表详情 /// - public sealed partial class FavoriteDetailPage : BasePage + public sealed partial class FavoriteDetailPage : BasePage, IRefreshablePage { FavoriteDetailVM favoriteDetailVM; public FavoriteDetailPage() @@ -192,5 +193,10 @@ private async void PlayAll_Click(object sender, RoutedEventArgs e) } }); } + + public async Task Refresh() + { + favoriteDetailVM.Refresh(); + } } } diff --git a/src/BiliLite.UWP/Pages/User/FavoritePage.xaml.cs b/src/BiliLite.UWP/Pages/User/FavoritePage.xaml.cs index 6349f5e0..45fb1924 100644 --- a/src/BiliLite.UWP/Pages/User/FavoritePage.xaml.cs +++ b/src/BiliLite.UWP/Pages/User/FavoritePage.xaml.cs @@ -4,18 +4,11 @@ using BiliLite.Modules; using BiliLite.Services; using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; +using System.Threading.Tasks; + using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 @@ -32,7 +25,7 @@ public enum OpenFavoriteType /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class FavoritePage : BasePage + public sealed partial class FavoritePage : BasePage, IRefreshablePage { MyFollowSeasonVM animeVM; MyFollowSeasonVM cinemaVM; @@ -164,5 +157,10 @@ private async void btnFavBoxDel_Click(object sender, RoutedEventArgs e) await videoVM.DelFavorite(data.id); videoVM.Refresh(); } + + public async Task Refresh() + { + videoVM.Refresh(); + } } } diff --git a/src/BiliLite.UWP/Pages/User/HistoryPage.xaml.cs b/src/BiliLite.UWP/Pages/User/HistoryPage.xaml.cs index 34d07b71..8cbacf75 100644 --- a/src/BiliLite.UWP/Pages/User/HistoryPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/User/HistoryPage.xaml.cs @@ -1,4 +1,5 @@ -using BiliLite.Models.Common; +using System.Threading.Tasks; +using BiliLite.Models.Common; using BiliLite.Services; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -14,7 +15,7 @@ namespace BiliLite.Pages.User /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class HistoryPage : BasePage + public sealed partial class HistoryPage : BasePage, IRefreshablePage { private readonly HistoryViewModel m_viewModel; public HistoryPage() @@ -109,5 +110,10 @@ private async void SearchBox_OnQuerySubmitted(AutoSuggestBox sender, AutoSuggest var keyword = sender.Text; await m_viewModel.SearchHistory(keyword); } + + public async Task Refresh() + { + m_viewModel.Refresh(); + } } } diff --git a/src/BiliLite.UWP/Pages/User/WatchlaterPage.xaml.cs b/src/BiliLite.UWP/Pages/User/WatchlaterPage.xaml.cs index cae560ae..f8c1f446 100644 --- a/src/BiliLite.UWP/Pages/User/WatchlaterPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/User/WatchlaterPage.xaml.cs @@ -1,19 +1,9 @@ using BiliLite.Models.Common; using BiliLite.Modules.User; using BiliLite.Services; -using System; using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Windows.UI.Xaml; +using System.Threading.Tasks; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 @@ -23,7 +13,7 @@ namespace BiliLite.Pages.User /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class WatchlaterPage : BasePage + public sealed partial class WatchlaterPage : BasePage, IRefreshablePage { WatchLaterVM watchLaterVM; public WatchlaterPage() @@ -72,5 +62,10 @@ private void Video_ItemClick(object sender, ItemClickEventArgs e) } }); } + + public async Task Refresh() + { + watchLaterVM.Refresh(); + } } } diff --git a/src/BiliLite.UWP/Pages/UserInfoPage.xaml.cs b/src/BiliLite.UWP/Pages/UserInfoPage.xaml.cs index b0df033f..7746477f 100644 --- a/src/BiliLite.UWP/Pages/UserInfoPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/UserInfoPage.xaml.cs @@ -1,4 +1,5 @@ -using BiliLite.Extensions; +using System.Threading.Tasks; +using BiliLite.Extensions; using BiliLite.Models.Common; using BiliLite.Models.Requests.Api; using BiliLite.Modules.User.UserDetail; @@ -34,7 +35,7 @@ public class UserInfoParameter /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class UserInfoPage : BasePage + public sealed partial class UserInfoPage : BasePage, IRefreshablePage { readonly UserDynamicViewModel m_userDynamicViewModel; UserDetailViewModel m_viewModel; @@ -405,5 +406,10 @@ private void BtnFollowingTag_OnClick(object sender, RoutedEventArgs e) { UserFollowingTagsFlyout.ShowAt(sender as DependencyObject); } + + public async Task Refresh() + { + throw new System.NotImplementedException(); + } } } diff --git a/src/BiliLite.UWP/Pages/VideoDetailPage.xaml.cs b/src/BiliLite.UWP/Pages/VideoDetailPage.xaml.cs index 9a282891..455f87bf 100644 --- a/src/BiliLite.UWP/Pages/VideoDetailPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/VideoDetailPage.xaml.cs @@ -41,7 +41,7 @@ public class VideoPlaylistItem public string Cover { get; set; } public string Title { get; set; } } - public sealed partial class VideoDetailPage : PlayPage + public sealed partial class VideoDetailPage : PlayPage, IRefreshablePage { private static readonly ILogger logger = GlobalLogger.FromCurrentType(); @@ -610,12 +610,17 @@ private async void btnDownload_Click(object sender, RoutedEventArgs e) await downloadDialog.ShowAsync(); } - private async void btnRefresh_Click(object sender, RoutedEventArgs e) + public async Task Refresh() { if (m_viewModel.Loading) return; await InitializeVideo(_id); } + private async void btnRefresh_Click(object sender, RoutedEventArgs e) + { + await Refresh(); + } + private void btnOpenQR_Click(object sender, RoutedEventArgs e) { qrFlyout.ShowAt(btnMore); diff --git a/src/BiliLite.UWP/Services/ShortcutKeyService.cs b/src/BiliLite.UWP/Services/ShortcutKeyService.cs new file mode 100644 index 00000000..04124b3e --- /dev/null +++ b/src/BiliLite.UWP/Services/ShortcutKeyService.cs @@ -0,0 +1,46 @@ +using BiliLite.Models.Functions; +using System.Collections.Generic; +using System.Linq; +using Windows.System; +using Windows.UI.Core; +using Windows.UI.Xaml; +using BiliLite.Pages; + +namespace BiliLite.Services +{ + public class ShortcutKeyService + { + private Dictionary> m_shortcutKeyMaps; + private IMainPage m_mainPage; + + public ShortcutKeyService() + { + m_shortcutKeyMaps = new Dictionary>(); + // TODO: 读取设置 + m_shortcutKeyMaps.Add(new RefreshShortcutFunction(), new List() { VirtualKey.Control, VirtualKey.R }); + m_shortcutKeyMaps.Add(new RefreshShortcutFunction(), new List() { VirtualKey.F5 }); + } + + public void SetMainPage(IMainPage mainPage) + { + m_mainPage = mainPage; + } + + public void HandleKeyDown(VirtualKey key) + { + foreach (var (shortcutKeyFunction, shortcutKeyCodes) in m_shortcutKeyMaps) + { + if (shortcutKeyCodes.LastOrDefault() != key) continue; + if (shortcutKeyCodes + .Select(keyCode => Window.Current.CoreWindow.GetKeyState(keyCode)) + .Any(keyState => !keyState.HasFlag(CoreVirtualKeyStates.Down))) + { + continue; + } + + var page = m_mainPage.CurrentPage; + shortcutKeyFunction.Action(page); + } + } + } +} diff --git a/src/BiliLite.UWP/Startup.cs b/src/BiliLite.UWP/Startup.cs index ed017e95..1b09041f 100644 --- a/src/BiliLite.UWP/Startup.cs +++ b/src/BiliLite.UWP/Startup.cs @@ -15,6 +15,7 @@ public void ConfigureServices(HostBuilderContext context, IServiceCollection ser services.AddDanmakuController(); services.AddSingleton(); + services.AddSingleton(); services.AddTransient(); services.AddQrCodeService(); From 8b1caa57741e334bb916e2a70d77cc97bfe697f3 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Tue, 23 Apr 2024 19:37:12 +0800 Subject: [PATCH 18/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E5=8A=A8=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserDynamicItemV2DataTemplateSelector.cs | 3 +++ .../Controls/Dynamic/DynamicV2Template.xaml | 1 + src/BiliLite.UWP/Models/Common/Constants.cs | 2 ++ .../UserDynamic/DynamicV2ItemViewModel.cs | 17 +++++++++++++++++ 4 files changed, 23 insertions(+) diff --git a/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs index 16f266df..6fdfc29a 100644 --- a/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs +++ b/src/BiliLite.UWP/Controls/DataTemplateSelectors/UserDynamicItemV2DataTemplateSelector.cs @@ -38,6 +38,7 @@ DataTemplate SelectRowTemplate(UserDynamicItemDataTemplateSelector selector, { Constants.DynamicTypes.MUSIC, (selector, model) => selector.MusicTemplate }, { Constants.DynamicTypes.COMMON_SQUARE, (selector, model) => selector.CommonSquareTemplate }, { Constants.DynamicTypes.LIVE_RCMD, (selector, model) => selector.LiveRcmdTemplate }, + { Constants.DynamicTypes.LIVE, (selector, model) => selector.LiveTemplate }, { Constants.DynamicTypes.CUSTOM_SEASON, (selector, model) => selector.CustomSeasonTemplate }, { Constants.DynamicTypes.CUSTOM_ARTICLE, (selector, model) => selector.CustomArticleTemplate }, { Constants.DynamicTypes.UGC_SEASON, (selector, model) => selector.UgcSeasonTemplate }, @@ -66,6 +67,8 @@ DataTemplate SelectRowTemplate(UserDynamicItemDataTemplateSelector selector, public DataTemplate LiveRcmdTemplate { get; set; } + public DataTemplate LiveTemplate { get; set; } + public DataTemplate UgcSeasonTemplate { get; set; } public DataTemplate CustomSeasonTemplate { get; set; } diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml index 182e0746..4aeac5dc 100644 --- a/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicV2Template.xaml @@ -17,6 +17,7 @@ Draw3x3Template="{StaticResource DynamicDraw3x3}" CommonSquareTemplate="{StaticResource DynamicCommonSquare}" LiveRcmdTemplate="{StaticResource DynamicLiveRcmd}" + LiveTemplate="{StaticResource DynamicLiveRcmd}" UgcSeasonTemplate="{StaticResource DynamicUgcSeason}" CustomSeasonTemplate="{StaticResource DynamicCustomSeason}" CustomArticleTemplate="{StaticResource DynamicCustomArticle}"> diff --git a/src/BiliLite.UWP/Models/Common/Constants.cs b/src/BiliLite.UWP/Models/Common/Constants.cs index 5363d086..6677c522 100644 --- a/src/BiliLite.UWP/Models/Common/Constants.cs +++ b/src/BiliLite.UWP/Models/Common/Constants.cs @@ -102,6 +102,8 @@ public static class DynamicTypes public const string LIVE_RCMD = "LiveRcmd"; + public const string LIVE = "Live"; + public const string UGC_SEASON = "UgcSeason"; public const string BANNER = "Banner"; diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs index ca187bb2..d90c4edc 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/DynamicV2ItemViewModel.cs @@ -59,6 +59,23 @@ public ModuleDynamic Dynamic { LiveInfo = JsonConvert.DeserializeObject(value.DynLiveRcmd.Content); } + + if (value.DynCommonLive != null) + { + LiveInfo = new DynLiveInfo() + { + PlayInfo = new DynLivePlayInfo() + { + Cover = value.DynCommonLive.Cover, + Title = value.DynCommonLive.Title, + AreaName = value.DynCommonLive.CoverLabel, + WatchedShow = new DynLiveWatchedShow() + { + TextLarge = value.DynCommonLive.CoverLabel2, + } + } + }; + } } } From 75378c6bbbafad1efc4f926e0b81e10c6e132602 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Thu, 25 Apr 2024 22:53:43 +0800 Subject: [PATCH 19/30] =?UTF-8?q?=E5=B0=81=E8=A3=85=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=E5=86=85=E6=B6=88=E6=81=AF=E6=8E=A7=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BD=8D=E7=BD=AE=E5=8F=8A=E5=8A=A8=E7=94=BB?= =?UTF-8?q?=EF=BC=8C=E5=88=87=E6=8D=A2=E5=88=86=E9=9B=86=E6=97=B6=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=E9=9F=B3=E9=87=8F=EF=BC=8C=E5=BF=AB=E6=8D=B7=E9=94=AE?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E6=92=AD=E6=94=BE=E9=80=9F=E5=BA=A6=E6=97=B6?= =?UTF-8?q?=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/BiliLite.UWP.csproj | 9 ++ src/BiliLite.UWP/Controls/PlayerControl.xaml | 2 + .../Controls/PlayerControl.xaml.cs | 102 ++++++++--------- src/BiliLite.UWP/Controls/PlayerToast.xaml | 40 +++++++ src/BiliLite.UWP/Controls/PlayerToast.xaml.cs | 45 ++++++++ .../Extensions/ControlsExtensions.cs | 4 +- .../Extensions/ViewModelExtensions.cs | 1 + .../Services/PlayerToastService.cs | 105 ++++++++++++++++++ src/BiliLite.UWP/Startup.cs | 1 + .../ViewModels/PlayerToastViewModel.cs | 9 ++ 10 files changed, 261 insertions(+), 57 deletions(-) create mode 100644 src/BiliLite.UWP/Controls/PlayerToast.xaml create mode 100644 src/BiliLite.UWP/Controls/PlayerToast.xaml.cs create mode 100644 src/BiliLite.UWP/Services/PlayerToastService.cs create mode 100644 src/BiliLite.UWP/ViewModels/PlayerToastViewModel.cs diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj index bc64e636..e3248a0e 100644 --- a/src/BiliLite.UWP/BiliLite.UWP.csproj +++ b/src/BiliLite.UWP/BiliLite.UWP.csproj @@ -143,6 +143,9 @@ DynamicItemV2Control.xaml + + PlayerToast.xaml + UserFollowingTagsFlyout.xaml @@ -174,8 +177,10 @@ + + @@ -974,6 +979,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/src/BiliLite.UWP/Controls/PlayerControl.xaml b/src/BiliLite.UWP/Controls/PlayerControl.xaml index c9e56aaa..111965a2 100644 --- a/src/BiliLite.UWP/Controls/PlayerControl.xaml +++ b/src/BiliLite.UWP/Controls/PlayerControl.xaml @@ -586,6 +586,8 @@ + + ToolTipContainer; + /// /// 铺满窗口事件 /// @@ -126,6 +129,8 @@ public BiliPlayUrlQualitesInfo playUrlInfo public PlayerControl() { m_viewModel = new PlayControlViewModel(); + m_playerToastService = App.ServiceProvider.GetRequiredService(); + m_playerToastService.Init(this); this.InitializeComponent(); dispRequest = new DisplayRequest(); playerHelper = new PlayerVM(); @@ -234,25 +239,6 @@ private async void PlayerControl_Loaded(object sender, RoutedEventArgs e) danmuTimer.Start(); timer_focus.Start(); - - // 检查音量是否偏低 - if (Player.Volume > 0.95) return; - var toolTipText = ""; - if (Player.Volume == 0) - { - toolTipText = "静音"; - } - else - { - toolTipText = "音量:" + Player.Volume.ToString("P"); - } - - TxtToolTip.Text = toolTipText; - ToolTip.Background = new SolidColorBrush(Color.FromArgb(90, 240, 240, 240)); - ToolTip.Visibility = Visibility.Visible; - await Task.Delay(2000); - ToolTip.Visibility = Visibility.Collapsed; - ToolTip.Background = new SolidColorBrush(Color.FromArgb(204, 255, 255, 255)); } private async void _systemMediaTransportControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args) @@ -322,10 +308,9 @@ private async void PlayerControl_KeyDown(CoreWindow sender, KeyEventArgs args) _position = 0; } Player.Position = _position; - TxtToolTip.Text = "进度:" + TimeSpan.FromSeconds(Player.Position).ToString(@"hh\:mm\:ss"); - ToolTip.Visibility = Visibility.Visible; - await Task.Delay(2000); - ToolTip.Visibility = Visibility.Collapsed; + + m_playerToastService.Show( + PlayerToastService.PROGRESS_KEY, "进度:" + TimeSpan.FromSeconds(Player.Position).ToString(@"hh\:mm\:ss")); } } @@ -344,34 +329,25 @@ private async void PlayerControl_KeyDown(CoreWindow sender, KeyEventArgs args) _position = Player.Duration; } Player.Position = _position; - TxtToolTip.Text = "进度:" + TimeSpan.FromSeconds(Player.Position).ToString(@"hh\:mm\:ss"); - ToolTip.Visibility = Visibility.Visible; - await Task.Delay(2000); - ToolTip.Visibility = Visibility.Collapsed; + + m_playerToastService.Show( + PlayerToastService.PROGRESS_KEY, "进度:" + TimeSpan.FromSeconds(Player.Position).ToString(@"hh\:mm\:ss")); } } break; case Windows.System.VirtualKey.Up: Player.Volume += 0.1; - TxtToolTip.Text = "音量:" + Player.Volume.ToString("P"); - ToolTip.Visibility = Visibility.Visible; - await Task.Delay(2000); - ToolTip.Visibility = Visibility.Collapsed; + m_playerToastService.Show(PlayerToastService.VOLUME_KEY, "音量:" + Player.Volume.ToString("P")); break; case Windows.System.VirtualKey.Down: Player.Volume -= 0.1; - if (Player.Volume == 0) - { - TxtToolTip.Text = "静音"; - } - else + var txtToolTipText = "静音"; + if (Player.Volume > 0) { - TxtToolTip.Text = "音量:" + Player.Volume.ToString("P"); + txtToolTipText = "音量:" + Player.Volume.ToString("P"); } - ToolTip.Visibility = Visibility.Visible; - await Task.Delay(2000); - ToolTip.Visibility = Visibility.Collapsed; + m_playerToastService.Show(PlayerToastService.VOLUME_KEY, txtToolTipText); break; case Windows.System.VirtualKey.Escape: IsFullScreen = false; @@ -404,10 +380,8 @@ private async void PlayerControl_KeyDown(CoreWindow sender, KeyEventArgs args) _position = Player.Duration; } Player.Position = _position; - TxtToolTip.Text = "跳过OP(快进90秒)"; - ToolTip.Visibility = Visibility.Visible; - await Task.Delay(2000); - ToolTip.Visibility = Visibility.Collapsed; + + m_playerToastService.Show(PlayerToastService.MSG_KEY, "跳过OP(快进90秒)"); } } break; @@ -456,7 +430,7 @@ private async void PlayerControl_KeyDown(CoreWindow sender, KeyEventArgs args) } BottomCBSpeed.SelectedIndex += 1; - + m_playerToastService.Show(PlayerToastService.SPEED_KEY,(BottomCBSpeed.SelectedItem as ComboBoxItem).Content.ToString()); break; case Windows.System.VirtualKey.F2: case (Windows.System.VirtualKey)222: @@ -467,6 +441,7 @@ private async void PlayerControl_KeyDown(CoreWindow sender, KeyEventArgs args) return; } BottomCBSpeed.SelectedIndex -= 1; + m_playerToastService.Show(PlayerToastService.SPEED_KEY, (BottomCBSpeed.SelectedItem as ComboBoxItem).Content.ToString()); break; case Windows.System.VirtualKey.F3: case Windows.System.VirtualKey.V: @@ -485,6 +460,25 @@ private async void PlayerControl_KeyDown(CoreWindow sender, KeyEventArgs args) } } + /// + /// 检查音量是否偏低 + /// + private void CheckVolumeLower() + { + // 检查音量是否偏低 + if (Player.Volume > 0.95) return; + var toolTipText = ""; + if (Player.Volume == 0) + { + toolTipText = "静音"; + } + else + { + toolTipText = "音量:" + Player.Volume.ToString("P"); + } + + m_playerToastService.Show(PlayerToastService.VOLUME_KEY, toolTipText); + } private void LoadDanmuSetting() { @@ -1056,6 +1050,8 @@ private async Task SetPlayItem(int index) await GetPlayerInfo(); + CheckVolumeLower(); + Player.ABPlay = VideoPlayHistoryHelper.FindABPlayHistory(CurrentPlayItem); if (Player.ABPlay == null) { @@ -1986,23 +1982,20 @@ private void StopHolding() private void StartHighRateSpeedPlay() { - TxtToolTip.Text = "倍速播放中"; - ToolTip.Visibility = Visibility.Visible; + m_playerToastService.KeepStart(PlayerToastService.ACCELERATING_KEY, "倍速播放中"); var highRatePlaySpeed = SettingService.GetValue(SettingConstants.Player.HIGH_RATE_PLAY_SPEED, 2.0d); Player.SetRate(highRatePlaySpeed); } private void StopHighRateSpeedPlay() { - ToolTip.Visibility = Visibility.Collapsed; + m_playerToastService.KeepClose(PlayerToastService.ACCELERATING_KEY); Player.SetRate(SettingService.GetValue(SettingConstants.Player.DEFAULT_VIDEO_SPEED, 1.0d)); } private void OnManipulationStarted(object sender, ManipulationStartedEventArgs e) { ssValue = 0; - //TxtToolTip.Text = ""; - ToolTip.Visibility = Visibility.Visible; if (e.Position.X < this.ActualWidth / 2) ManipulatingBrightness = true; @@ -2068,7 +2061,6 @@ private void OnManipulationCompleted(object sender, ManipulationCompletedEventAr { Player.Position = Player.Position + ssValue; } - ToolTip.Visibility = Visibility.Collapsed; } private void Grid_PointerPressed(object sender, PointerRoutedEventArgs e) @@ -2204,8 +2196,7 @@ private void HandleSlideProgressDelta(double delta) pos = Player.Duration; //txt_Post.Text = ts.Hours.ToString("00") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00") + "/" + mediaElement.MediaPlayer.PlaybackSession.NaturalDuration.TimeSpan.Hours.ToString("00") + ":" + mediaElement.MediaPlayer.PlaybackSession.NaturalDuration.TimeSpan.Minutes.ToString("00") + ":" + mediaElement.MediaPlayer.PlaybackSession.NaturalDuration.TimeSpan.Seconds.ToString("00"); - TxtToolTip.Text = TimeSpan.FromSeconds(pos).ToString(@"hh\:mm\:ss"); - //Notify.ShowMessageToast(ts.Hours.ToString("00") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00"), 3000); + m_playerToastService.Show(PlayerToastService.PROGRESS_KEY, TimeSpan.FromSeconds(pos).ToString(@"hh\:mm\:ss")); } private void HandleSlideVolumeDelta(double delta) @@ -2226,8 +2217,7 @@ private void HandleSlideVolumeDelta(double delta) Player.Volume = volume; //slider_V.Value += d; } - TxtToolTip.Text = "音量:" + Player.Volume.ToString("P"); - //Notify.ShowMessageToast("音量:" + mediaElement.MediaPlayer.Volume.ToString("P"), 3000); + m_playerToastService.Show(PlayerToastService.VOLUME_KEY, "音量:" + Player.Volume.ToString("P")); } private void HandleSlideBrightnessDelta(double delta) { @@ -2240,7 +2230,7 @@ private void HandleSlideBrightnessDelta(double delta) { Brightness = Math.Max(Brightness - dd, 0); } - TxtToolTip.Text = "亮度:" + Math.Abs(Brightness - 1).ToString("P"); + m_playerToastService.Show(PlayerToastService.BRIGHTNESS_KEY, "亮度:" + Math.Abs(Brightness - 1).ToString("P")); } #endregion private void BottomBtnList_Click(object sender, RoutedEventArgs e) diff --git a/src/BiliLite.UWP/Controls/PlayerToast.xaml b/src/BiliLite.UWP/Controls/PlayerToast.xaml new file mode 100644 index 00000000..b9779b25 --- /dev/null +++ b/src/BiliLite.UWP/Controls/PlayerToast.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BiliLite.UWP/Controls/PlayerToast.xaml.cs b/src/BiliLite.UWP/Controls/PlayerToast.xaml.cs new file mode 100644 index 00000000..1b3e7dd6 --- /dev/null +++ b/src/BiliLite.UWP/Controls/PlayerToast.xaml.cs @@ -0,0 +1,45 @@ +using System.Threading.Tasks; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media.Animation; +using BiliLite.ViewModels; + +//https://go.microsoft.com/fwlink/?LinkId=234236 上介绍了“用户控件”项模板 + +namespace BiliLite.Controls +{ + public sealed partial class PlayerToast : UserControl + { + private readonly PlayerToastViewModel m_viewModel; + + public PlayerToast(PlayerToastViewModel viewModel) + { + m_viewModel = viewModel; + this.InitializeComponent(); + } + + public string Text + { + set => m_viewModel.Text = value; + } + + public void Show() + { + var storyboard = (Storyboard)this.Resources["ShowToast"]; + storyboard.Begin(); + } + + public async Task Hide() + { + var storyboard = (Storyboard)this.Resources["HideToast"]; + storyboard.Begin(); + var tcs = new TaskCompletionSource(); + + storyboard.Completed += (s, e) => + { + tcs.SetResult(true); + }; + storyboard.Begin(); + await tcs.Task; + } + } +} diff --git a/src/BiliLite.UWP/Extensions/ControlsExtensions.cs b/src/BiliLite.UWP/Extensions/ControlsExtensions.cs index 955ccf7a..c192b9d3 100644 --- a/src/BiliLite.UWP/Extensions/ControlsExtensions.cs +++ b/src/BiliLite.UWP/Extensions/ControlsExtensions.cs @@ -1,4 +1,5 @@ -using BiliLite.Dialogs; +using BiliLite.Controls; +using BiliLite.Dialogs; using Microsoft.Extensions.DependencyInjection; namespace BiliLite.Extensions @@ -9,6 +10,7 @@ public static IServiceCollection AddControls(this IServiceCollection services) { services.AddTransient(); services.AddTransient(); + services.AddTransient(); return services; } } diff --git a/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs b/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs index 0ffd7fd9..a4e5d98a 100644 --- a/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs +++ b/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs @@ -35,6 +35,7 @@ public static IServiceCollection AddViewModels(this IServiceCollection services) services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); return services; } } diff --git a/src/BiliLite.UWP/Services/PlayerToastService.cs b/src/BiliLite.UWP/Services/PlayerToastService.cs new file mode 100644 index 00000000..6952292f --- /dev/null +++ b/src/BiliLite.UWP/Services/PlayerToastService.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Timers; +using System.Threading.Tasks; +using Windows.UI.Xaml.Controls; +using BiliLite.Controls; +using Windows.UI.Core; +using Microsoft.Extensions.DependencyInjection; + +namespace BiliLite.Services +{ + public class PlayerToastService + { + private PlayerControl m_playerControl; + private int[] m_bottomList = new[] { 170, 240, 310, 380, 450, 520 }; + private readonly Dictionary m_showPlayerToasts = new Dictionary(); + private readonly Dictionary m_showPlayerToastTimers = new Dictionary(); + public const string VOLUME_KEY = "Volume"; + public const string BRIGHTNESS_KEY = "Brightness"; + public const string PROGRESS_KEY = "Progress"; + public const string MSG_KEY = "Msg"; + public const string ACCELERATING_KEY = "Accelerating"; + public const string SPEED_KEY = "Speed"; + private readonly IServiceProvider m_serviceProvider; + + public PlayerToastService(IServiceProvider serviceProvider) + { + m_serviceProvider = serviceProvider; + } + + public void Init(PlayerControl control) + { + m_playerControl = control; + } + + public async void KeepStart(string key, string msg) + { + var newToast = m_serviceProvider.GetRequiredService(); + newToast.Height = 80; + newToast.Width = 200; + newToast.Text = msg; + Canvas.SetLeft(newToast, 0); + double distanceFromBottom = m_bottomList[m_showPlayerToasts.Count]; + while (m_playerControl.ActualHeight == 0) + { + await Task.Delay(500); + } + Canvas.SetTop(newToast, m_playerControl.ActualHeight - distanceFromBottom); + + m_showPlayerToasts.Add(key, newToast); + m_playerControl.PlayerToastContainer.Children.Add(newToast); + newToast.Show(); + } + + public async void KeepClose(string key) + { + if (!m_showPlayerToasts.TryGetValue(key, out var toast)) return; + m_playerControl.PlayerToastContainer.Children.Remove(toast); + m_showPlayerToasts.Remove(key); + } + + public async void Show(string key, string msg) + { + if (m_showPlayerToasts.TryGetValue(key, out var toast)) + { + toast.Text = msg; + var timer = m_showPlayerToastTimers[key]; + timer.Stop(); + timer.Start(); + return; + } + + var newToast = m_serviceProvider.GetRequiredService(); + newToast.Height = 80; + newToast.Width = 200; + newToast.Text = msg; + Canvas.SetLeft(newToast, 0); + double distanceFromBottom = m_bottomList[m_showPlayerToasts.Count]; + while (m_playerControl.ActualHeight == 0) + { + await Task.Delay(500); + } + Canvas.SetTop(newToast, m_playerControl.ActualHeight - distanceFromBottom); + + m_showPlayerToasts.Add(key, newToast); + m_playerControl.PlayerToastContainer.Children.Add(newToast); + newToast.Show(); + + var newTimer = new Timer(); + newTimer.Interval = 2000; + newTimer.Elapsed += async (o, e) => + { + await m_playerControl.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + newTimer.Stop(); + m_playerControl.PlayerToastContainer.Children.Remove(newToast); + m_showPlayerToasts.Remove(key); + m_showPlayerToastTimers.Remove(key); + }); + }; + m_showPlayerToastTimers.Add(key, newTimer); + newTimer.Start(); + } + } +} diff --git a/src/BiliLite.UWP/Startup.cs b/src/BiliLite.UWP/Startup.cs index 1b09041f..d6eb4f88 100644 --- a/src/BiliLite.UWP/Startup.cs +++ b/src/BiliLite.UWP/Startup.cs @@ -16,6 +16,7 @@ public void ConfigureServices(HostBuilderContext context, IServiceCollection ser services.AddSingleton(); services.AddSingleton(); + services.AddTransient(); services.AddTransient(); services.AddQrCodeService(); diff --git a/src/BiliLite.UWP/ViewModels/PlayerToastViewModel.cs b/src/BiliLite.UWP/ViewModels/PlayerToastViewModel.cs new file mode 100644 index 00000000..75276632 --- /dev/null +++ b/src/BiliLite.UWP/ViewModels/PlayerToastViewModel.cs @@ -0,0 +1,9 @@ +using BiliLite.ViewModels.Common; + +namespace BiliLite.ViewModels +{ + public class PlayerToastViewModel : BaseViewModel + { + public string Text { get; set; } + } +} From 6580cb5c4e4d2d0a2a30a4d40b191520753e1f04 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Thu, 25 Apr 2024 23:03:21 +0800 Subject: [PATCH 20/30] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=8E=9F=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E5=99=A8=E5=86=85=E6=B6=88=E6=81=AF=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/Controls/PlayerControl.xaml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/BiliLite.UWP/Controls/PlayerControl.xaml b/src/BiliLite.UWP/Controls/PlayerControl.xaml index 111965a2..13918e7a 100644 --- a/src/BiliLite.UWP/Controls/PlayerControl.xaml +++ b/src/BiliLite.UWP/Controls/PlayerControl.xaml @@ -588,19 +588,6 @@ - - - - - - From 9592191f4915d160b0706c23fef43f14025cf2c2 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Fri, 26 Apr 2024 19:26:43 +0800 Subject: [PATCH 21/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=BD=AC=E5=8F=91?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E7=94=A8=E6=88=B7=E5=92=8C=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E7=82=B9=E5=87=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml index 79695504..3820962e 100644 --- a/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml +++ b/src/BiliLite.UWP/Controls/Dynamic/DynamicItemV2Control.xaml @@ -97,6 +97,8 @@ @@ -112,6 +114,8 @@ + + + - - - - - - 全部 - - - - - 投稿视频 - - - - - 追番追剧 - - - - - 专栏 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs deleted file mode 100644 index 7d6ce0bf..00000000 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicAllPage.xaml.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using BiliLite.Services; -using BiliLite.Models.Common; -using BiliLite.Models.Requests.Api; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Navigation; -using BiliLite.Extensions; -using BiliLite.ViewModels.UserDynamic; -using Microsoft.Extensions.DependencyInjection; -using BiliLite.Models.Common.Comment; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media.Animation; - -// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 - -namespace BiliLite.Pages.Home -{ - /// - /// 可用于自身或导航至 Frame 内部的空白页。 - /// - public sealed partial class UserDynamicAllPage : Page,IRefreshablePage - { - readonly UserDynamicAllViewModel m_viewModel; - private bool m_isStaggered = false; - private UserDynamicShowType m_currentShowType; - - public UserDynamicAllPage() - { - m_viewModel = App.ServiceProvider.GetRequiredService(); - m_viewModel.OpenCommentEvent += UserDynamicViewModelOpenCommentEvent; - this.InitializeComponent(); - m_currentShowType = (UserDynamicShowType)DynPivot.SelectedIndex; - } - - protected override async void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - - SetStaggered(); - if (e.NavigationMode == NavigationMode.New && m_viewModel.DynamicItems == null) - { - await m_viewModel.GetDynamicItems(); - if (SettingService.GetValue("动态切换提示", true) && SettingService.GetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0) != 1) - { - SettingService.SetValue("动态切换提示", false); - Notify.ShowMessageToast("右下角可以切换成瀑布流显示哦~", 5); - } - } - } - - 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"]; - - //顶部 - GridTopBar.MaxWidth = double.MaxValue; - GridTopBar.Margin = new Thickness(0, 0, 0, 4); - BorderTopBar.CornerRadius = new CornerRadius(0); - BorderTopBar.Margin = new Thickness(0); - } - - private void SetListCore() - { - m_isStaggered = false; - //右下角按钮 - BtnGrid.Visibility = Visibility.Visible; - BtnList.Visibility = Visibility.Collapsed; - //XAML - ListDyn.ItemsPanel = (ItemsPanelTemplate)this.Resources["ListPanel"]; - - //顶部 - GridTopBar.MaxWidth = 800; - GridTopBar.Margin = new Thickness(8, 0, 8, 0); - BorderTopBar.CornerRadius = new CornerRadius(4); - BorderTopBar.Margin = new Thickness(12, 4, 12, 4); - } - - private async void BtnRefreshDynamic_OnClick(object sender, RoutedEventArgs e) - { - await Refresh(); - } - - 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 async void Pivot_OnSelectionChanged(object sender, SelectionChangedEventArgs e) - { - var showType = (UserDynamicShowType)DynPivot.SelectedIndex; - if (showType == m_currentShowType) return; - m_currentShowType = showType; - await m_viewModel.GetDynamicItems(showType: showType); - } - - 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(); - } - - public async Task Refresh() - { - await m_viewModel.GetDynamicItems(showType: m_currentShowType); - } - } -} diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicPage.xaml b/src/BiliLite.UWP/Pages/Home/UserDynamicPage.xaml index cc8f093d..ec9ec508 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicPage.xaml +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicPage.xaml @@ -15,7 +15,7 @@ - + - + + + - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + - - - + + diff --git a/src/BiliLite.UWP/Pages/Home/UserDynamicPage.xaml.cs b/src/BiliLite.UWP/Pages/Home/UserDynamicPage.xaml.cs index d7bffab0..5e307ec1 100644 --- a/src/BiliLite.UWP/Pages/Home/UserDynamicPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/Home/UserDynamicPage.xaml.cs @@ -1,13 +1,17 @@ -using BiliLite.Services; +using System.Linq; +using System.Threading.Tasks; +using BiliLite.Services; using BiliLite.Models.Common; using BiliLite.Models.Requests.Api; -using BiliLite.Models.Requests.Api.User; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; using BiliLite.Extensions; -using BiliLite.Models.Common.UserDynamic; using BiliLite.ViewModels.UserDynamic; +using Microsoft.Extensions.DependencyInjection; +using BiliLite.Models.Common.Comment; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media.Animation; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 @@ -16,91 +20,28 @@ namespace BiliLite.Pages.Home /// /// 可用于自身或导航至 Frame 内部的空白页。 /// - public sealed partial class UserDynamicPage : Page + public sealed partial class UserDynamicPage : Page,IRefreshablePage { - readonly UserDynamicViewModel m_userDynamicViewModel; - private bool IsStaggered { get; set; } = false; + readonly UserDynamicAllViewModel m_viewModel; + private bool m_isStaggered = false; + private UserDynamicShowType m_currentShowType; + public UserDynamicPage() { + m_viewModel = App.ServiceProvider.GetRequiredService(); + m_viewModel.OpenCommentEvent += UserDynamicViewModelOpenCommentEvent; this.InitializeComponent(); - m_userDynamicViewModel = new UserDynamicViewModel(); - m_userDynamicViewModel.OpenCommentEvent += UserDynamicViewModelOpenCommentEvent; - splitView.PaneClosed += SplitView_PaneClosed; - this.DataContext = m_userDynamicViewModel; - if (SettingService.GetValue(SettingConstants.UI.CACHE_HOME, true)) - { - this.NavigationCacheMode = NavigationCacheMode.Enabled; - } - else - { - this.NavigationCacheMode = NavigationCacheMode.Disabled; - } + m_currentShowType = (UserDynamicShowType)DynPivot.SelectedIndex; } - private void SplitView_PaneClosed(SplitView sender, object args) - { - comment.ClearComment(); - repost.UserDynamicRepostViewModel.Clear(); - } - string dynamic_id; - private void UserDynamicViewModelOpenCommentEvent(object sender, UserDynamicItemDisplayViewModel e) - { - // splitView.IsPaneOpen = true; - dynamic_id = e.DynamicID; - pivotRight.SelectedIndex = 1; - repostCount.Text = e.ShareCount.ToString(); - commentCount.Text = e.CommentCount.ToString(); - CommentApi.CommentType commentType = CommentApi.CommentType.Dynamic; - var id = e.ReplyID; - switch (e.Type) - { - - case UserDynamicDisplayType.Photo: - commentType = CommentApi.CommentType.Photo; - break; - case UserDynamicDisplayType.Video: - - commentType = CommentApi.CommentType.Video; - break; - case UserDynamicDisplayType.Season: - id = e.OneRowInfo.AID; - commentType = CommentApi.CommentType.Video; - break; - case UserDynamicDisplayType.ShortVideo: - commentType = CommentApi.CommentType.MiniVideo; - break; - case UserDynamicDisplayType.Music: - commentType = CommentApi.CommentType.Song; - break; - case UserDynamicDisplayType.Article: - commentType = CommentApi.CommentType.Article; - break; - case UserDynamicDisplayType.MediaList: - if (e.OneRowInfo.Tag != "收藏夹") - commentType = CommentApi.CommentType.Video; - break; - default: - id = e.DynamicID; - break; - } - - //comment.LoadComment(new Controls.LoadCommentInfo() - //{ - // commentMode = (int)commentType, - // commentSort = Api.CommentApi.commentSort.Hot, - // oid = id - //}); - Notify.ShowComment(id, (int)commentType, CommentApi.CommentSort.Hot); - } - - protected async override void OnNavigatedTo(NavigationEventArgs e) + protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); SetStaggered(); - if (e.NavigationMode == NavigationMode.New && m_userDynamicViewModel.Items == null) + if (e.NavigationMode == NavigationMode.New && m_viewModel.DynamicItems == null) { - await m_userDynamicViewModel.GetDynamicItems(); + await m_viewModel.GetDynamicItems(); if (SettingService.GetValue("动态切换提示", true) && SettingService.GetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0) != 1) { SettingService.SetValue("动态切换提示", false); @@ -109,89 +50,148 @@ protected async override void OnNavigatedTo(NavigationEventArgs e) } } - void SetStaggered() + private void SetStaggered() { var staggered = SettingService.GetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0) == 1; - if (staggered != IsStaggered) + if (staggered != m_isStaggered) { - IsStaggered = staggered; + m_isStaggered = staggered; if (staggered) { - btnGrid_Click(this, null); + SetGridCore(); } else { - btnList_Click(this, null); + SetListCore(); } } } - private void pivot_SelectionChanged(object sender, SelectionChangedEventArgs e) + private void SetGridCore() { - if ((int)m_userDynamicViewModel.UserDynamicType == pivot.SelectedIndex) return; - m_userDynamicViewModel.UserDynamicType = (UserDynamicType)pivot.SelectedIndex; - m_userDynamicViewModel.Refresh(); + m_isStaggered = true; + BtnGrid.Visibility = Visibility.Collapsed; + BtnList.Visibility = Visibility.Visible; + //XAML + ListDyn.ItemsPanel = (ItemsPanelTemplate)this.Resources["GridPanel"]; + + //顶部 + GridTopBar.MaxWidth = double.MaxValue; + GridTopBar.Margin = new Thickness(0, 0, 0, 4); + BorderTopBar.CornerRadius = new CornerRadius(0); + BorderTopBar.Margin = new Thickness(0); } - private void btnGrid_Click(object sender, RoutedEventArgs e) + private void SetListCore() { - SettingService.SetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 1); - IsStaggered = true; - btnGrid.Visibility = Visibility.Collapsed; - btnList.Visibility = Visibility.Visible; + m_isStaggered = false; + //右下角按钮 + BtnGrid.Visibility = Visibility.Visible; + BtnList.Visibility = Visibility.Collapsed; + //XAML + ListDyn.ItemsPanel = (ItemsPanelTemplate)this.Resources["ListPanel"]; + //顶部 - gridTopBar.MaxWidth = double.MaxValue; - gridTopBar.Margin = new Thickness(0, 0, 0, 4); - borderTopBar.CornerRadius = new CornerRadius(0); - borderTopBar.Margin = new Thickness(0); + GridTopBar.MaxWidth = 800; + GridTopBar.Margin = new Thickness(8, 0, 8, 0); + BorderTopBar.CornerRadius = new CornerRadius(4); + BorderTopBar.Margin = new Thickness(12, 4, 12, 4); + } - //XAML - // var tmp = @" "; - // var xaml = $@" - // {tmp} - // "; - //list.ItemsPanel = (ItemsPanelTemplate)XamlReader.Load(xaml); - list.ItemsPanel = (ItemsPanelTemplate)this.Resources["GridPanel"]; + private async void BtnRefreshDynamic_OnClick(object sender, RoutedEventArgs e) + { + await Refresh(); } - private void btnList_Click(object sender, RoutedEventArgs e) + private void BtnTop_OnClick(object sender, RoutedEventArgs e) + { + ListDyn.ScrollIntoView(ListDyn.Items.FirstOrDefault()); + } + + private void BtnList_OnClick(object sender, RoutedEventArgs e) { - IsStaggered = false; - //右下角按钮 - btnGrid.Visibility = Visibility.Visible; - btnList.Visibility = Visibility.Collapsed; - //设置 SettingService.SetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 0); - //顶部 - gridTopBar.MaxWidth = 800; - gridTopBar.Margin = new Thickness(8, 0, 8, 0); - borderTopBar.CornerRadius = new CornerRadius(4); - borderTopBar.Margin = new Thickness(12, 4, 12, 4); - //XAML - // var tmp = @" "; - // var xaml = $@" - // {tmp} - // "; - //list.ItemsPanel = (ItemsPanelTemplate)XamlReader.Load(xaml); - list.ItemsPanel = (ItemsPanelTemplate)this.Resources["ListPanel"]; + SetListCore(); } - private void btnTop_Click(object sender, RoutedEventArgs e) + private void BtnGrid_OnClick(object sender, RoutedEventArgs e) { - list.ScrollIntoView(list.Items[0]); + SettingService.SetValue(SettingConstants.UI.DYNAMIC_DISPLAY_MODE, 1); + SetGridCore(); } - private void pivotRight_SelectionChanged(object sender, SelectionChangedEventArgs e) + private async void Pivot_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { - if (pivotRight.SelectedIndex == 0 && splitView.IsPaneOpen && (repost.UserDynamicRepostViewModel.Items == null || repost.UserDynamicRepostViewModel.Items.Count == 0)) + var showType = (UserDynamicShowType)DynPivot.SelectedIndex; + if (showType == m_currentShowType) return; + m_currentShowType = showType; + await m_viewModel.GetDynamicItems(showType: showType); + } + + 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) { - repost.LoadData(dynamic_id); + 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(); + } + + public async Task Refresh() + { + await m_viewModel.GetDynamicItems(showType: m_currentShowType); } } } diff --git a/src/BiliLite.UWP/ViewModels/Home/HomeViewModel.cs b/src/BiliLite.UWP/ViewModels/Home/HomeViewModel.cs index b7a8694f..9ab3e3f2 100644 --- a/src/BiliLite.UWP/ViewModels/Home/HomeViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/Home/HomeViewModel.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using AutoMapper; -using BiliLite.Models.Common; using BiliLite.Models.Common.Home; using BiliLite.Modules; using BiliLite.Services; @@ -15,6 +14,7 @@ public class HomeViewModel : BaseViewModel { #region Fields + private static readonly ILogger _logger = GlobalLogger.FromCurrentType(); private readonly IMapper m_mapper; private readonly Account m_account; @@ -26,8 +26,7 @@ public HomeViewModel() { m_account = new Account(); m_mapper = App.ServiceProvider.GetRequiredService(); - var homeNavItemList = SettingService.GetValue(SettingConstants.UI.HOEM_ORDER, DefaultHomeNavItems.GetDefaultHomeNavItems()); - homeNavItemList = DefaultHomeNavItems.CheckHomeNavItems(homeNavItemList); + var homeNavItemList = DefaultHomeNavItems.GetHomeNavItems(); HomeNavItems = m_mapper.Map>(homeNavItemList); SelectItem = HomeNavItems.FirstOrDefault(); if (!SettingService.Account.Logined) return; From fd4f323ffe2877179ba6d8b8e6f45233586c468b Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sun, 28 Apr 2024 19:35:29 +0800 Subject: [PATCH 26/30] =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E4=BF=9D=E6=8C=81=E9=9F=B3=E9=87=8F=E5=92=8C=E4=BA=AE=E5=BA=A6?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controls/PlayerControl.xaml.cs | 34 ++++++---- .../Models/Common/SettingConstants.cs | 38 +++++++++++ src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs | 13 ++-- src/BiliLite.UWP/Pages/SettingPage.xaml | 12 ++++ src/BiliLite.UWP/Pages/SettingPage.xaml.cs | 64 +++++++++++++++++++ 5 files changed, 145 insertions(+), 16 deletions(-) diff --git a/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs b/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs index 6b2de3ea..6b420b4b 100644 --- a/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs +++ b/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs @@ -461,9 +461,9 @@ private async void PlayerControl_KeyDown(CoreWindow sender, KeyEventArgs args) } /// - /// 检查音量是否偏低 + /// 检查音量和亮度是否偏低 /// - private void CheckVolumeLower() + private void CheckVolumeAndBrightnessLower() { // 检查音量是否偏低 if (Player.Volume > 0.95) return; @@ -478,6 +478,10 @@ private void CheckVolumeLower() } m_playerToastService.Show(PlayerToastService.VOLUME_KEY, toolTipText); + + // 检查亮度是否偏低 + if (Math.Abs(Brightness - 1) > 0.8) return; + m_playerToastService.Show(PlayerToastService.BRIGHTNESS_KEY, "亮度:" + Math.Abs(Brightness - 1).ToString("P")); } private void LoadDanmuSetting() @@ -654,16 +658,21 @@ private void LoadDanmuSetting() } private void LoadPlayerSetting() { - //音量 - Player.Volume = SettingService.GetValue(SettingConstants.Player.PLAYER_VOLUME, 1.0); - SliderVolume.ValueChanged += new RangeBaseValueChangedEventHandler((e, args) => + Player.Volume = SettingService.GetValue(SettingConstants.Player.PLAYER_VOLUME, SettingConstants.Player.DEFAULT_PLAYER_VOLUME); + + var lockPlayerVolume = SettingService.GetValue(SettingConstants.Player.LOCK_PLAYER_VOLUME, SettingConstants.Player.DEFAULT_LOCK_PLAYER_VOLUME); + if (!lockPlayerVolume) { - SettingService.SetValue(SettingConstants.Player.PLAYER_VOLUME, SliderVolume.Value); - }); + SliderVolume.ValueChanged += new RangeBaseValueChangedEventHandler((e, args) => + { + SettingService.SetValue(SettingConstants.Player.PLAYER_VOLUME, SliderVolume.Value); + }); + } //亮度 - //_brightness = SettingService.GetValue(SettingConstants.Player.PLAYER_BRIGHTNESS, 0); - //BrightnessShield.Opacity = _brightness; + lockBrightness = SettingService.GetValue(SettingConstants.Player.LOCK_PLAYER_BRIGHTNESS, SettingConstants.Player.DEFAULT_LOCK_PLAYER_BRIGHTNESS); + _brightness = SettingService.GetValue(SettingConstants.Player.PLAYER_BRIGHTNESS, SettingConstants.Player.DEFAULT_PLAYER_BRIGHTNESS); + BrightnessShield.Opacity = _brightness; //播放模式 var selectedValue = (PlayUrlCodecMode)SettingService.GetValue(SettingConstants.Player.DEFAULT_VIDEO_TYPE, (int)DefaultVideoTypeOptions.DEFAULT_VIDEO_TYPE); @@ -1050,7 +1059,7 @@ private async Task SetPlayItem(int index) await GetPlayerInfo(); - CheckVolumeLower(); + CheckVolumeAndBrightnessLower(); Player.ABPlay = VideoPlayHistoryHelper.FindABPlayHistory(CurrentPlayItem); if (Player.ABPlay == null) @@ -1918,6 +1927,7 @@ private void TopBtnCloseDanmaku_Click(object sender, RoutedEventArgs e) double ssValue = 0; bool ManipulatingBrightness = false; double _brightness = 0; + private bool lockBrightness = true; PlayerHoldingAction m_playerHoldingAction; double Brightness { @@ -1926,8 +1936,8 @@ double Brightness { _brightness = value; BrightnessShield.Opacity = value; - //SettingHelper.SetValue(SettingHelper.Player.PLAYER_BRIGHTNESS, _brightness); - //} + if(!lockBrightness) + SettingService.SetValue(SettingConstants.Player.PLAYER_BRIGHTNESS, _brightness); } } private void InitializeGesture() diff --git a/src/BiliLite.UWP/Models/Common/SettingConstants.cs b/src/BiliLite.UWP/Models/Common/SettingConstants.cs index fd82144e..cef81b4c 100644 --- a/src/BiliLite.UWP/Models/Common/SettingConstants.cs +++ b/src/BiliLite.UWP/Models/Common/SettingConstants.cs @@ -510,11 +510,49 @@ public class Player /// [SettingKey(typeof(double))] public const string PLAYER_VOLUME = "PlayerVolume"; + + /// + /// 音量默认值 + /// + [SettingDefaultValue] + public const double DEFAULT_PLAYER_VOLUME = 1.0; + /// /// 亮度 /// [SettingKey(typeof(double))] public const string PLAYER_BRIGHTNESS = "PlayeBrightness"; + + /// + /// 亮度默认值 + /// + [SettingDefaultValue] + public const double DEFAULT_PLAYER_BRIGHTNESS = 0; + + /// + /// 锁定播放器音量设置(播放器内修改音量时不写设置) + /// + [SettingKey(typeof(bool))] + public const string LOCK_PLAYER_VOLUME = "LockPlayerVolume"; + + /// + /// 锁定播放器音量设置默认值 + /// + [SettingDefaultValue] + public const bool DEFAULT_LOCK_PLAYER_VOLUME = false; + + /// + /// 锁定播放器亮度设置(播放器内修改亮度时不写设置) + /// + [SettingKey(typeof(bool))] + public const string LOCK_PLAYER_BRIGHTNESS = "LockPlayerBrightness"; + + /// + /// 锁定播放器亮度设置默认值 + /// + [SettingDefaultValue] + public const bool DEFAULT_LOCK_PLAYER_BRIGHTNESS = true; + /// /// A-B 循环播放模式的播放记录 /// diff --git a/src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs b/src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs index 91ea9b3e..6694a636 100644 --- a/src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs @@ -534,15 +534,18 @@ private void PreLoadSetting() private void LoadSetting() { //音量 - m_player.Volume = SettingService.GetValue(SettingConstants.Player.PLAYER_VOLUME, 1.0); + m_player.Volume = SettingService.GetValue(SettingConstants.Player.PLAYER_VOLUME, SettingConstants.Player.DEFAULT_PLAYER_VOLUME); SliderVolume.Value = m_player.Volume; + var lockPlayerVolume = SettingService.GetValue(SettingConstants.Player.LOCK_PLAYER_VOLUME, SettingConstants.Player.DEFAULT_LOCK_PLAYER_VOLUME); SliderVolume.ValueChanged += (e, args) => { m_player.Volume = SliderVolume.Value; - SettingService.SetValue(SettingConstants.Player.PLAYER_VOLUME, SliderVolume.Value); + if(!lockPlayerVolume) + SettingService.SetValue(SettingConstants.Player.PLAYER_VOLUME, SliderVolume.Value); }; //亮度 - _brightness = SettingService.GetValue(SettingConstants.Player.PLAYER_BRIGHTNESS, 0); + lockBrightness = SettingService.GetValue(SettingConstants.Player.LOCK_PLAYER_BRIGHTNESS, SettingConstants.Player.DEFAULT_LOCK_PLAYER_BRIGHTNESS); + _brightness = SettingService.GetValue(SettingConstants.Player.PLAYER_BRIGHTNESS, SettingConstants.Player.DEFAULT_PLAYER_BRIGHTNESS); BrightnessShield.Opacity = _brightness; //弹幕顶部距离 @@ -1185,6 +1188,7 @@ private void Grid_ManipulationStarted(object sender, ManipulationStartedRoutedEv } + private bool lockBrightness = true; double _brightness; double Brightness { @@ -1193,7 +1197,8 @@ double Brightness { _brightness = value; BrightnessShield.Opacity = value; - SettingService.SetValue(SettingConstants.Player.PLAYER_BRIGHTNESS, _brightness); + if (!lockBrightness) + SettingService.SetValue(SettingConstants.Player.PLAYER_BRIGHTNESS, _brightness); } } diff --git a/src/BiliLite.UWP/Pages/SettingPage.xaml b/src/BiliLite.UWP/Pages/SettingPage.xaml index 7aeddf26..655c2dd1 100644 --- a/src/BiliLite.UWP/Pages/SettingPage.xaml +++ b/src/BiliLite.UWP/Pages/SettingPage.xaml @@ -319,6 +319,18 @@ + 音量 + + + 亮度 + + + 锁定播放器音量设置(播放器内修改音量时不写设置) + + + 锁定播放器亮度设置(播放器内修改亮度时不写设置) + + 自动打开AI字幕 部分自动生成的AI字幕会与视频自带字幕冲突 diff --git a/src/BiliLite.UWP/Pages/SettingPage.xaml.cs b/src/BiliLite.UWP/Pages/SettingPage.xaml.cs index ce97db6d..f59c01c7 100644 --- a/src/BiliLite.UWP/Pages/SettingPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/SettingPage.xaml.cs @@ -433,6 +433,70 @@ private void LoadPlayer() }; }; + // 音量 + NumBoxVolume.Value = Math.Round((SettingService.GetValue(SettingConstants.Player.PLAYER_VOLUME, + SettingConstants.Player.DEFAULT_PLAYER_VOLUME)) * 100, 2); + NumBoxVolume.Loaded += (sender, e) => + { + NumBoxVolume.ValueChanged += (obj, args) => + { + if (NumBoxVolume.Value > 100) + { + NumBoxVolume.Value = 100; + } + + if (NumBoxVolume.Value < 0) + { + NumBoxVolume.Value = 0; + } + SettingService.SetValue(SettingConstants.Player.PLAYER_VOLUME, NumBoxVolume.Value/100); + }; + }; + + // 锁定播放器音量设置 + SwLockPlayerVolume.IsOn = SettingService.GetValue(SettingConstants.Player.LOCK_PLAYER_VOLUME, SettingConstants.Player.DEFAULT_LOCK_PLAYER_VOLUME); + SwLockPlayerVolume.Loaded += (sender, e) => + { + SwLockPlayerVolume.Toggled += (obj, args) => + { + SettingService.SetValue(SettingConstants.Player.LOCK_PLAYER_VOLUME, SwLockPlayerVolume.IsOn); + }; + }; + + // 亮度 + NumBoxBrightness.Value = Math.Round( + (Math.Abs(SettingService.GetValue( + SettingConstants.Player.PLAYER_BRIGHTNESS, + SettingConstants.Player.DEFAULT_PLAYER_BRIGHTNESS) - 1)) * 100, 2); + NumBoxBrightness.Loaded += (sender, e) => + { + NumBoxBrightness.ValueChanged += (obj, args) => + { + if (NumBoxBrightness.Value > 100) + { + NumBoxBrightness.Value = 100; + } + + if (NumBoxBrightness.Value < 0) + { + NumBoxBrightness.Value = 0; + } + + var brightness = Math.Abs((NumBoxBrightness.Value / 100) - 1); + SettingService.SetValue(SettingConstants.Player.PLAYER_BRIGHTNESS, brightness); + }; + }; + + // 锁定播放器亮度设置 + SwLockPlayerBrightness.IsOn = SettingService.GetValue(SettingConstants.Player.LOCK_PLAYER_BRIGHTNESS, SettingConstants.Player.DEFAULT_LOCK_PLAYER_BRIGHTNESS); + SwLockPlayerBrightness.Loaded += (sender, e) => + { + SwLockPlayerBrightness.Toggled += (obj, args) => + { + SettingService.SetValue(SettingConstants.Player.LOCK_PLAYER_BRIGHTNESS, SwLockPlayerBrightness.IsOn); + }; + }; + //自动打开AI字幕 swPlayerSettingAutoOpenAISubtitle.IsOn = SettingService.GetValue(SettingConstants.Player.AUTO_OPEN_AI_SUBTITLE, false); swPlayerSettingAutoOpenAISubtitle.Loaded += new RoutedEventHandler((sender, e) => From eca55d518d7c30a2038afba8ee212855b2493835 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sun, 28 Apr 2024 19:38:03 +0800 Subject: [PATCH 27/30] =?UTF-8?q?=E8=A7=86=E9=A2=91=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=90=8E=E4=B8=8A=E6=8A=A5=E8=BF=9B=E5=BA=A6?= =?UTF-8?q?0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/Controls/PlayerControl.xaml.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs b/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs index 6b420b4b..3b77c24a 100644 --- a/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs +++ b/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs @@ -2443,7 +2443,7 @@ private void Player_PlayBufferEnd(object sender, EventArgs e) m_danmakuController.Resume(); } - private void Player_PlayMediaEnded(object sender, EventArgs e) + private async void Player_PlayMediaEnded(object sender, EventArgs e) { if (CurrentPlayItem.is_interaction) { @@ -2458,7 +2458,10 @@ private void Player_PlayMediaEnded(object sender, EventArgs e) } _logger.Debug("视频结束,上报进度"); - playerHelper.ReportHistory(CurrentPlayItem, Player.Duration).RunWithoutAwait(); + await playerHelper.ReportHistory(CurrentPlayItem, Player.Duration); + + _logger.Debug("进度归0"); + await playerHelper.ReportHistory(CurrentPlayItem, 0); //列表顺序播放 if (PlayerSettingPlayMode.SelectedIndex == 0) { From fa64b2851738bb08df12f0fd52657279cba156c3 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sun, 28 Apr 2024 19:38:44 +0800 Subject: [PATCH 28/30] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=97=B6=E9=BB=98=E8=AE=A4=E5=AF=BC=E5=87=BA=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=E4=B8=BA=E8=A7=86=E9=A2=91=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/Pages/DownloadPage.xaml.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/BiliLite.UWP/Pages/DownloadPage.xaml.cs b/src/BiliLite.UWP/Pages/DownloadPage.xaml.cs index a1478c93..cb03cb9c 100644 --- a/src/BiliLite.UWP/Pages/DownloadPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/DownloadPage.xaml.cs @@ -16,6 +16,7 @@ using BiliLite.Models.Common.Video.PlayUrlInfos; using BiliLite.ViewModels.Download; using Microsoft.Extensions.DependencyInjection; +using System.Text.RegularExpressions; // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板 @@ -306,7 +307,8 @@ private async void OutputFile(DownloadedItem data, DownloadedSubItem item) savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary; savePicker.FileTypeChoices.Add("MP4", new List() { ".mp4" }); - savePicker.SuggestedFileName = "导出的视频"; + var fileName = Regex.Replace(data.Title + "-" + item.Title, "[<>/\\\\|:\":?*]", ""); + savePicker.SuggestedFileName = fileName; var file = await savePicker.PickSaveFileAsync(); if (file == null) return; From 079211449d27180e561dd8b05f5ce1de1ff58127 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sun, 28 Apr 2024 19:39:29 +0800 Subject: [PATCH 29/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E9=A1=B5=E8=A7=86=E9=A2=91=E5=8A=A8=E6=80=81Tab=E7=AC=AC?= =?UTF-8?q?=E4=BA=8C=E9=A1=B5=E5=8A=A0=E8=BD=BD=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewModels/UserDynamic/UserDynamicAllViewModel.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs index 17f8b6c4..45188291 100644 --- a/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs +++ b/src/BiliLite.UWP/ViewModels/UserDynamic/UserDynamicAllViewModel.cs @@ -37,6 +37,7 @@ public class UserDynamicAllViewModel : BaseViewModel, IUserDynamicCommands private int m_page = 1; private string m_offset = null; private string m_baseline = null; + private UserDynamicShowType m_showType; #endregion @@ -333,7 +334,7 @@ public async void LoadMore() return; } - await GetDynamicItems(m_page + 1); + await GetDynamicItems(m_page + 1, m_showType); } public async Task GetDynamicItems(int page = 1, UserDynamicShowType showType = UserDynamicShowType.All) @@ -343,6 +344,7 @@ public async Task GetDynamicItems(int page = 1, UserDynamicShowType showType = U CanLoadMore = false; Loading = true; m_page = page; + m_showType = showType; if (page == 1) { m_offset = null; From f69abe3b4e9078d9e8cbbc6e413030f82bc8f533 Mon Sep 17 00:00:00 2001 From: ywmoyue Date: Sun, 28 Apr 2024 19:40:08 +0800 Subject: [PATCH 30/30] =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E7=9B=B4=E6=92=AD=E5=BA=95=E9=83=A8=E7=A4=BC=E7=89=A9=E6=A0=8F?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BiliLite.UWP/Models/Common/SettingConstants.cs | 12 ++++++++++++ src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs | 5 +++++ src/BiliLite.UWP/Pages/SettingPage.xaml | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/BiliLite.UWP/Models/Common/SettingConstants.cs b/src/BiliLite.UWP/Models/Common/SettingConstants.cs index cef81b4c..8770c526 100644 --- a/src/BiliLite.UWP/Models/Common/SettingConstants.cs +++ b/src/BiliLite.UWP/Models/Common/SettingConstants.cs @@ -441,6 +441,18 @@ public class Live /// [SettingKey(typeof(string))] public const string DEFAULT_LIVE_PLAY_URL_SOURCE = "DefaultLivePlayUrlSource"; + + /// + /// 显示底部礼物栏 + /// + [SettingKey(typeof(bool))] + public const string SHOW_BOTTOM_GIFT_BAR = "ShowBottomGiftBar"; + + /// + /// 默认显示底部礼物栏 + /// + [SettingDefaultValue] + public const bool DEFAULT_SHOW_BOTTOM_GIFT_BAR = true; } public class Player diff --git a/src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs b/src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs index 6694a636..76d8294f 100644 --- a/src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs +++ b/src/BiliLite.UWP/Pages/LiveDetailPage.xaml.cs @@ -659,6 +659,10 @@ private void LoadSetting() m_liveRoomViewModel.ReceiveLotteryMsg = !LiveSettingDotReceiveLotteryMsg.IsOn; SettingService.SetValue(SettingConstants.Live.HIDE_LOTTERY, LiveSettingDotReceiveLotteryMsg.IsOn); }); + + // 显示底部礼物栏 + m_viewModel.ShowBottomGiftBar = SettingService.GetValue(SettingConstants.Live.SHOW_BOTTOM_GIFT_BAR, + SettingConstants.Live.DEFAULT_SHOW_BOTTOM_GIFT_BAR); } public void ChangeTitle(string title) @@ -1257,6 +1261,7 @@ private async void PlayUrlSourceComboBox_OnSelectionChanged(object sender, Selec private void BottomBtnSwitchGiftBar_Click(object sender, RoutedEventArgs e) { m_viewModel.ShowBottomGiftBar = !m_viewModel.ShowBottomGiftBar; + SettingService.SetValue(SettingConstants.Live.SHOW_BOTTOM_GIFT_BAR, m_viewModel.ShowBottomGiftBar); } } } diff --git a/src/BiliLite.UWP/Pages/SettingPage.xaml b/src/BiliLite.UWP/Pages/SettingPage.xaml index 655c2dd1..b4513de7 100644 --- a/src/BiliLite.UWP/Pages/SettingPage.xaml +++ b/src/BiliLite.UWP/Pages/SettingPage.xaml @@ -504,7 +504,7 @@ - 直播弹幕 + 直播