diff --git a/BiliLite.sln b/BiliLite.sln index c7201e94..3ab038f3 100644 --- a/BiliLite.sln +++ b/BiliLite.sln @@ -28,6 +28,8 @@ Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "BiliLite.Packages", "src\Bi EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BiliLite.Win32Tools", "src\BiliLite.Win32Tools\BiliLite.Win32Tools.csproj", "{B44AD18B-7805-4FFB-A29E-C57D09C8D425}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackgroundTasks", "src\BackgroundTasks\BackgroundTasks.csproj", "{32288EDB-3F7F-479A-8303-7BB6705E0636}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -200,6 +202,26 @@ Global {B44AD18B-7805-4FFB-A29E-C57D09C8D425}.Release|x64.Build.0 = Release|Any CPU {B44AD18B-7805-4FFB-A29E-C57D09C8D425}.Release|x86.ActiveCfg = Release|Any CPU {B44AD18B-7805-4FFB-A29E-C57D09C8D425}.Release|x86.Build.0 = Release|Any CPU + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|ARM.ActiveCfg = Debug|ARM + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|ARM.Build.0 = Debug|ARM + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|ARM64.Build.0 = Debug|ARM64 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|x64.ActiveCfg = Debug|x64 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|x64.Build.0 = Debug|x64 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|x86.ActiveCfg = Debug|x86 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Debug|x86.Build.0 = Debug|x86 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|Any CPU.Build.0 = Release|Any CPU + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|ARM.ActiveCfg = Release|ARM + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|ARM.Build.0 = Release|ARM + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|ARM64.ActiveCfg = Release|ARM64 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|ARM64.Build.0 = Release|ARM64 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|x64.ActiveCfg = Release|x64 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|x64.Build.0 = Release|x64 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|x86.ActiveCfg = Release|x86 + {32288EDB-3F7F-479A-8303-7BB6705E0636}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/BackgroundTasks/BackgroundTasks.csproj b/src/BackgroundTasks/BackgroundTasks.csproj new file mode 100644 index 00000000..ecad63af --- /dev/null +++ b/src/BackgroundTasks/BackgroundTasks.csproj @@ -0,0 +1,154 @@ + + + + + latest + Debug + AnyCPU + {32288EDB-3F7F-479A-8303-7BB6705E0636} + winmdobj + Properties + BackgroundTasks + BackgroundTasks + zh-CN + UAP + 10.0.22621.0 + 10.0.19041.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + false + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + prompt + 4 + + + x86 + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + false + prompt + + + x86 + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + false + prompt + + + ARM + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + false + prompt + + + ARM + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + false + prompt + + + ARM64 + true + bin\ARM64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + false + prompt + + + ARM64 + bin\ARM64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + false + prompt + + + x64 + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + false + prompt + true + + + x64 + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + false + prompt + + + PackageReference + + + + + + + + 6.2.14 + + + + + {8b90b3b3-844b-4610-9dcf-c9b250182ae3} + BiliLite.UWP + + + + 14.0 + + + + + + + \ No newline at end of file diff --git a/src/BackgroundTasks/Properties/AssemblyInfo.cs b/src/BackgroundTasks/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..a8a3fb81 --- /dev/null +++ b/src/BackgroundTasks/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("BackgroundTasks")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("BackgroundTasks")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/src/BackgroundTasks/TileFeedBackgroundTask.cs b/src/BackgroundTasks/TileFeedBackgroundTask.cs new file mode 100644 index 00000000..98a217a8 --- /dev/null +++ b/src/BackgroundTasks/TileFeedBackgroundTask.cs @@ -0,0 +1,23 @@ +using System.Diagnostics; +using Windows.ApplicationModel.Background; +using BiliLite.Extensions.Notifications; + +namespace BackgroundTasks +{ + public sealed class TileFeedBackgroundTask : IBackgroundTask + { + public void Run(IBackgroundTaskInstance taskInstance) + { + Debug.WriteLine("================ debug to updating tiles ================"); + + // Get a deferral, to prevent the task from closing prematurely + // while asynchronous code is still running. + var deferral = taskInstance.GetDeferral(); + + NotificationShowExtensions.Tile(); + + // Inform the system that the task is finished. + deferral.Complete(); + } + } +} \ No newline at end of file diff --git a/src/BiliLite.Packages/Package.appxmanifest b/src/BiliLite.Packages/Package.appxmanifest index 3b9a830e..717d0de8 100644 --- a/src/BiliLite.Packages/Package.appxmanifest +++ b/src/BiliLite.Packages/Package.appxmanifest @@ -61,6 +61,12 @@ + + + + + @@ -72,4 +78,14 @@ + + + + CLRHost.dll + + + + diff --git a/src/BiliLite.UWP/App.xaml.cs b/src/BiliLite.UWP/App.xaml.cs index ce6e7b5f..d240fc7b 100644 --- a/src/BiliLite.UWP/App.xaml.cs +++ b/src/BiliLite.UWP/App.xaml.cs @@ -1,8 +1,11 @@ using BiliLite.Extensions; using BiliLite.Models.Common; using BiliLite.Models.Events; +using BiliLite.Pages; using BiliLite.Services; +using BiliLite.Services.Notification; using FFmpegInteropX; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Toolkit.Uwp.Helpers; using System; @@ -14,8 +17,7 @@ using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; -using BiliLite.Pages; -using Microsoft.Extensions.DependencyInjection; +using BiliLite.Extensions.Notifications; namespace BiliLite { @@ -205,6 +207,7 @@ private async void InitBili() // await Task.Delay(200); // 防止初始屏幕闪烁 } } + //圆角 App.Current.Resources["ImageCornerRadius"] = new CornerRadius(SettingService.GetValue(SettingConstants.UI.IMAGE_CORNER_RADIUS, 0)); await AppHelper.SetRegions(); @@ -292,5 +295,12 @@ private void RegisterService() logger.Error("Start Host Error", ex); } } + + protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args) + { + //base.OnBackgroundActivated(args); + //IBackgroundTaskInstance taskInstance = args.TaskInstance; + await NotificationShowExtensions.Tile(); + } } } \ No newline at end of file diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj index 84b3684f..cd3ac582 100644 --- a/src/BiliLite.UWP/BiliLite.UWP.csproj +++ b/src/BiliLite.UWP/BiliLite.UWP.csproj @@ -262,6 +262,7 @@ + @@ -279,6 +280,10 @@ + + + + @@ -1537,6 +1542,9 @@ 6.1.1 + + 7.1.3 + 6.1.1 diff --git a/src/BiliLite.UWP/Controls/Settings/UISettingsControl.xaml b/src/BiliLite.UWP/Controls/Settings/UISettingsControl.xaml index 67f861e6..71de8f30 100644 --- a/src/BiliLite.UWP/Controls/Settings/UISettingsControl.xaml +++ b/src/BiliLite.UWP/Controls/Settings/UISettingsControl.xaml @@ -200,6 +200,14 @@ + + + + + + + diff --git a/src/BiliLite.UWP/Controls/Settings/UISettingsControl.xaml.cs b/src/BiliLite.UWP/Controls/Settings/UISettingsControl.xaml.cs index 2e85ee31..54b614a0 100644 --- a/src/BiliLite.UWP/Controls/Settings/UISettingsControl.xaml.cs +++ b/src/BiliLite.UWP/Controls/Settings/UISettingsControl.xaml.cs @@ -10,6 +10,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.UI.Xaml.Controls; using Microsoft.Toolkit.Uwp.UI; +using BiliLite.Extensions.Notifications; +using Windows.ApplicationModel.Background; //https://go.microsoft.com/fwlink/?LinkId=234236 上介绍了“用户控件”项模板 @@ -131,6 +133,24 @@ private void LoadUI() }; }; + //动态磁贴 + SwitchTile.IsOn = SettingService.GetValue(SettingConstants.UI.ENABLE_NOTIFICATION_TILES, false); + SwitchTile.Loaded += (sender, e) => + { + SwitchTile.Toggled += (obj, args) => + { + SettingService.SetValue(SettingConstants.UI.ENABLE_NOTIFICATION_TILES, SwitchTile.IsOn); + if (SwitchTile.IsOn) + { + RegisterBackgroundTask(); + } + else + { + // TODO: UnregisterBackgroundTask + } + }; + }; + //图片圆角半径 numImageCornerRadius.Value = SettingService.GetValue(SettingConstants.UI.IMAGE_CORNER_RADIUS, 0); ImageCornerRadiusExample.CornerRadius = new CornerRadius(numImageCornerRadius.Value); @@ -361,5 +381,13 @@ private void menuRemoveHomeItem_Click(object sender, RoutedEventArgs e) ExceptHomeNavItems(); Notify.ShowMessageToast("更改成功,重启生效"); } + + private void RegisterBackgroundTask() + { + NotificationRegisterExtensions.BackgroundTask("DisposableTileFeedBackgroundTask"); + NotificationRegisterExtensions.BackgroundTask("TileFeedBackgroundTask", new TimeTrigger(15, false)); + //NotificationRegisterExtensions.BackgroundTask("TileFeedBackgroundTask", + // "BackgroundTasks.TileFeedBackgroundTask", new TimeTrigger(15, false)); + } } } diff --git a/src/BiliLite.UWP/Extensions/Notifications/NotificationRegisterExtensions.cs b/src/BiliLite.UWP/Extensions/Notifications/NotificationRegisterExtensions.cs new file mode 100644 index 00000000..4611448b --- /dev/null +++ b/src/BiliLite.UWP/Extensions/Notifications/NotificationRegisterExtensions.cs @@ -0,0 +1,99 @@ +using System; +using Windows.ApplicationModel.Background; + +namespace BiliLite.Extensions.Notifications +{ + public class NotificationRegisterExtensions + { + /// + /// 单次执行后台任务 + /// + /// + public static async void BackgroundTask(string taskName) + { + BackgroundExecutionManager.RemoveAccess(); + var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync(); + if (backgroundAccessStatus == BackgroundAccessStatus.AllowedSubjectToSystemPolicy || + backgroundAccessStatus == BackgroundAccessStatus.AlwaysAllowed) + { + foreach (var task in BackgroundTaskRegistration.AllTasks) + { + if (task.Value.Name == taskName) + { + task.Value.Unregister(true); + } + } + + var taskBuilder = new BackgroundTaskBuilder() + { + Name = taskName, + }; + var trigger = new ApplicationTrigger(); + taskBuilder.SetTrigger(trigger); + taskBuilder.Register(); + await trigger.RequestAsync(); + } + } + + /// + /// 注册进程内后台任务 + /// + /// + /// + public static async void BackgroundTask(string taskName, IBackgroundTrigger trigger) + { + BackgroundExecutionManager.RemoveAccess(); + var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync(); + if (backgroundAccessStatus == BackgroundAccessStatus.AllowedSubjectToSystemPolicy || + backgroundAccessStatus == BackgroundAccessStatus.AlwaysAllowed) + { + foreach (var task in BackgroundTaskRegistration.AllTasks) + { + if (task.Value.Name == taskName) + { + task.Value.Unregister(true); + } + } + + var taskBuilder = new BackgroundTaskBuilder() + { + Name = taskName, + }; + taskBuilder.SetTrigger(trigger); + taskBuilder.Register(); + } + } + + /// + /// (不可用)注册进程外后台任务 + /// + /// + /// + /// + public static async void BackgroundTask(string taskName, string taskEntryPoint, IBackgroundTrigger trigger) + { + BackgroundExecutionManager.RemoveAccess(); + var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync(); + if (backgroundAccessStatus == BackgroundAccessStatus.AllowedSubjectToSystemPolicy || + backgroundAccessStatus == BackgroundAccessStatus.AlwaysAllowed) + { + foreach (var task in BackgroundTaskRegistration.AllTasks) + { + if (task.Value.Name == taskName) + { + task.Value.Unregister(true); + } + } + + + var taskBuilder = new BackgroundTaskBuilder() + { + Name = taskName, + TaskEntryPoint = taskEntryPoint + }; + taskBuilder.SetTrigger(trigger); + taskBuilder.Register(); + } + } + } +} \ No newline at end of file diff --git a/src/BiliLite.UWP/Extensions/Notifications/NotificationShowExtensions.cs b/src/BiliLite.UWP/Extensions/Notifications/NotificationShowExtensions.cs new file mode 100644 index 00000000..d42a988a --- /dev/null +++ b/src/BiliLite.UWP/Extensions/Notifications/NotificationShowExtensions.cs @@ -0,0 +1,47 @@ +using System.Threading.Tasks; +using Windows.UI.Notifications; +using BiliLite.Models.Common.Notifications.Template; +using BiliLite.Services.Notification; +using Microsoft.Extensions.DependencyInjection; + +namespace BiliLite.Extensions.Notifications +{ + public class NotificationShowExtensions + { + public static async Task Tile() + { + // Create a tile update manager for the specified syndication feed. + var updater = TileUpdateManager.CreateTileUpdaterForApplication(); + updater.Clear(); + updater.EnableNotificationQueue(true); + + var liveTileHelper = App.ServiceProvider.GetRequiredService(); + + await liveTileHelper.RefreshTile(); + foreach (var tile in liveTileHelper.TileFurnace) + { + var content = TileTemplate.LiveTile(tile); + var notification = new TileNotification(content.GetXml()) + { + Tag = tile.Name, + }; + updater.Update(notification); + } + } + + public static void Dialog() + { + + } + + public static void MessageDialog() + { + + } + + public static void Toast() + { + + } + } +} diff --git a/src/BiliLite.UWP/Models/Common/Notifications/NotificationTile.cs b/src/BiliLite.UWP/Models/Common/Notifications/NotificationTile.cs new file mode 100644 index 00000000..d41f1401 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/Notifications/NotificationTile.cs @@ -0,0 +1,11 @@ +namespace BiliLite.Models.Common.Notifications +{ + public class NotificationTile + { + public string Name { get; set; } + + public string Description { get; set; } + + public string Url { get; set; } + } +} \ No newline at end of file diff --git a/src/BiliLite.UWP/Models/Common/Notifications/Template/TileTemplate.cs b/src/BiliLite.UWP/Models/Common/Notifications/Template/TileTemplate.cs new file mode 100644 index 00000000..0e6701c3 --- /dev/null +++ b/src/BiliLite.UWP/Models/Common/Notifications/Template/TileTemplate.cs @@ -0,0 +1,94 @@ +using Microsoft.Toolkit.Uwp.Notifications; + +namespace BiliLite.Models.Common.Notifications.Template +{ + public class TileTemplate + { + public static TileContent LiveTile(NotificationTile notificationTile) => new TileContent() + { + // 创建静态磁贴对象并返回 + Visual = new TileVisual() + { + Branding = TileBranding.NameAndLogo, + TileMedium = new TileBinding() + { + Content = new TileBindingContentAdaptive() + { + Children = + { + new AdaptiveText() + { + Text = notificationTile.Description, + HintMaxLines = 3, + HintWrap = true, + }, + new AdaptiveText() + { + Text = notificationTile.Name, + HintStyle = AdaptiveTextStyle.CaptionSubtle, + HintAlign = AdaptiveTextAlign.Center, + }, + }, + PeekImage = new TilePeekImage() + { + Source = notificationTile.Url, + HintOverlay = 30, + }, + } + }, + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() + { + Children = + { + new AdaptiveText() + { + Text = notificationTile.Description, + HintStyle = AdaptiveTextStyle.Body, + HintMaxLines = 2, + HintWrap = true, + }, + new AdaptiveText() + { + Text = notificationTile.Name, + HintAlign = AdaptiveTextAlign.Center, + }, + }, + BackgroundImage = new TileBackgroundImage() + { + Source = notificationTile.Url, + }, + } + }, + TileLarge = new TileBinding() + { + Content = new TileBindingContentAdaptive() + { + Children = + { + new AdaptiveText() + { + Text = notificationTile.Description, + HintStyle = AdaptiveTextStyle.Subtitle, + HintMaxLines = 5, + HintWrap = true, + }, + new AdaptiveText() {}, + new AdaptiveText() + { + Text = notificationTile.Name, + HintStyle = AdaptiveTextStyle.Base, + HintAlign = AdaptiveTextAlign.Center, + }, + }, + BackgroundImage = new TileBackgroundImage() + { + Source = notificationTile.Url, + }, + } + } + } + }; + } +} diff --git a/src/BiliLite.UWP/Models/Common/SettingConstants.cs b/src/BiliLite.UWP/Models/Common/SettingConstants.cs index 18e3cf0b..77bcdb67 100644 --- a/src/BiliLite.UWP/Models/Common/SettingConstants.cs +++ b/src/BiliLite.UWP/Models/Common/SettingConstants.cs @@ -234,6 +234,12 @@ public class UI [SettingDefaultValue] public const double DEFAULT_TAB_ITEM_MIN_WIDTH = 192; + + /// + /// 是否启用动态磁贴 + /// + // 因为要开关时注册磁贴服务,所以不设置SettingKey + public const string ENABLE_NOTIFICATION_TILES = "EnableNotificationTiles"; } public class Account diff --git a/src/BiliLite.UWP/Package.appxmanifest b/src/BiliLite.UWP/Package.appxmanifest index 8ffbb2a4..9957f3a1 100644 --- a/src/BiliLite.UWP/Package.appxmanifest +++ b/src/BiliLite.UWP/Package.appxmanifest @@ -57,7 +57,7 @@ - + diff --git a/src/BiliLite.UWP/Services/Notification/LiveTileService.cs b/src/BiliLite.UWP/Services/Notification/LiveTileService.cs new file mode 100644 index 00000000..149ba20b --- /dev/null +++ b/src/BiliLite.UWP/Services/Notification/LiveTileService.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using BiliLite.Models.Common.Notifications; + +namespace BiliLite.Services.Notification +{ + public class LiveTileService + { + public List TileFurnace = new List(); + + public async Task RefreshTile() + { + TileFurnace.Clear(); + // TODO: 取热门/动态/推荐数据 + var sample = new NotificationTile() + { + Name = "BiliLIte", + Description = "", + Url = @"Assets/SplashScreen.png", + }; + TileFurnace.Add(sample); + } + } +} diff --git a/src/BiliLite.UWP/Startup.cs b/src/BiliLite.UWP/Startup.cs index 97dd28e4..69dc22c7 100644 --- a/src/BiliLite.UWP/Startup.cs +++ b/src/BiliLite.UWP/Startup.cs @@ -1,6 +1,7 @@ using BiliLite.Extensions; using BiliLite.Services; using BiliLite.Services.Biz; +using BiliLite.Services.Notification; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -15,6 +16,7 @@ public void ConfigureServices(HostBuilderContext context, IServiceCollection ser services.AddSingleton(); services.AddTransient(); + services.AddSingleton(); services.AddMapper(); services.AddViewModels(); services.AddControls();