托盘图标

This commit is contained in:
Genteure 2020-11-28 13:02:57 +08:00
parent 3e5f8d100e
commit f41f5fefb9
16 changed files with 364 additions and 73 deletions

View File

@ -51,20 +51,20 @@ namespace BililiveRecorder.Core
return name;
}
public static bool CopyPropertiesTo<T>(this T val1, T val2) where T : class
public static bool CopyPropertiesTo<T>(this T source, T target) where T : class
{
if (val1 == null || val2 == null || val1 == val2) { return false; }
foreach (var p in val1.GetType().GetProperties())
if (source == null || target == null || source == target) { return false; }
foreach (var p in source.GetType().GetProperties())
{
if (Attribute.IsDefined(p, typeof(DoNotCopyProperty)))
{
continue;
}
var val = p.GetValue(val1);
if (val == p.GetValue(val2))
var val = p.GetValue(source);
if (val == null || !val.Equals(p.GetValue(target)))
{
p.SetValue(val2, val);
p.SetValue(target, val);
}
}
return true;

View File

@ -14,6 +14,7 @@
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
<FontFamily x:Key="ContentControlThemeFontFamily">Microsoft YaHei</FontFamily>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@ -1,9 +1,9 @@
using NLog;
using Squirrel;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using NLog;
using Squirrel;
namespace BililiveRecorder.WPF
{

View File

@ -97,11 +97,18 @@
<Compile Include="Controls\RoomCard.xaml.cs">
<DependentUpon>RoomCard.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\TaskbarIconControl.xaml.cs">
<DependentUpon>TaskbarIconControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\TaskbarIconTrayPopup.xaml.cs">
<DependentUpon>TaskbarIconTrayPopup.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\WorkDirectorySelectorDialog.xaml.cs">
<DependentUpon>WorkDirectorySelectorDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Converters\ClipEnabledToBooleanConverter.cs" />
<Compile Include="Converters\EnumToBooleanConverter.cs" />
<Compile Include="Converters\IsNullToVisibilityConverter.cs" />
<Compile Include="Converters\ShortRoomIdToVisibilityConverter.cs" />
<Compile Include="Converters\ValueConverterGroup.cs" />
<Compile Include="Models\LogModel.cs" />
@ -154,6 +161,14 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\TaskbarIconControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\TaskbarIconTrayPopup.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\WorkDirectorySelectorDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -0,0 +1,37 @@
<UserControl
x:Class="BililiveRecorder.WPF.Controls.TaskbarIconControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:tb="http://www.hardcodet.net/taskbar"
xmlns:local="clr-namespace:BililiveRecorder.WPF.Controls"
xmlns:wpf="clr-namespace:BililiveRecorder.WPF"
xmlns:page="clr-namespace:BililiveRecorder.WPF.Pages"
xmlns:conv="clr-namespace:BililiveRecorder.WPF.Converters"
mc:Ignorable="d">
<UserControl.Resources>
<conv:IsNullToVisibilityConverter x:Key="IsNullToVisibilityConverter"/>
</UserControl.Resources>
<tb:TaskbarIcon x:Name="TaskbarIcon" IconSource="/ico.ico" TrayLeftMouseUp="TaskbarIcon_TrayLeftMouseUp"
Visibility="{Binding Recorder, Converter={StaticResource IsNullToVisibilityConverter}}"
ToolTipText="B站录播姬" PopupActivation="RightClick"
>
<tb:TaskbarIcon.TrayToolTip>
<Border
Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
BorderBrush="{DynamicResource SystemControlBackgroundAccentBrush}"
BorderThickness="1"
CornerRadius="5">
<StackPanel Margin="10">
<TextBlock Style="{DynamicResource SubtitleTextBlockStyle}" Text="B站录播姬"/>
<TextBlock Text="{Binding Recorder.Config.WorkDirectory,Mode=OneWay}"/>
</StackPanel>
</Border>
</tb:TaskbarIcon.TrayToolTip>
<tb:TaskbarIcon.TrayPopup>
<local:TaskbarIconTrayPopup/>
</tb:TaskbarIcon.TrayPopup>
</tb:TaskbarIcon>
</UserControl>

View File

@ -0,0 +1,40 @@
using System.Windows;
using System.Windows.Controls;
using Hardcodet.Wpf.TaskbarNotification;
namespace BililiveRecorder.WPF.Controls
{
/// <summary>
/// Interaction logic for TaskbarIconControl.xaml
/// </summary>
public partial class TaskbarIconControl : UserControl
{
public TaskbarIconControl()
{
InitializeComponent();
// AddHandler(NewMainWindow.ShowBalloonTipEvent, (RoutedEventHandler)UserControl_ShowBalloonTip);
if (Application.Current.MainWindow is NewMainWindow nmw)
{
nmw.ShowBalloonTipCallback = (title, msg, sym) =>
{
TaskbarIcon.ShowBalloonTip(title, msg, sym);
};
}
}
private void TaskbarIcon_TrayLeftMouseUp(object sender, RoutedEventArgs e)
{
// RaiseEvent(new RoutedEventArgs(NewMainWindow.SuperActivateEvent));
(Application.Current.MainWindow as NewMainWindow)?.SuperActivateAction();
}
/*
private void UserControl_ShowBalloonTip(object sender, RoutedEventArgs e)
{
var f = e as NewMainWindow.ShowBalloonTipRoutedEventArgs;
TaskbarIcon.ShowBalloonTip(f.Title, f.Message, f.Symbol);
}
*/
}
}

View File

@ -0,0 +1,68 @@
<UserControl
x:Class="BililiveRecorder.WPF.Controls.TaskbarIconTrayPopup"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:local="clr-namespace:BililiveRecorder.WPF.Controls"
xmlns:models="clr-namespace:BililiveRecorder.WPF.Models"
xmlns:converter="clr-namespace:BililiveRecorder.WPF.Converters"
mc:Ignorable="d" d:DataContext="{d:DesignInstance Type=models:RootModel}">
<UserControl.Resources>
<converter:BoolToValueConverter x:Key="BooleanToVisibilityConverter"
TrueValue="{x:Static Visibility.Visible}"
FalseValue="{x:Static Visibility.Hidden}" />
</UserControl.Resources>
<Border Height="250" Width="300"
Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
BorderBrush="{DynamicResource SystemControlBackgroundAccentBrush}"
BorderThickness="1"
CornerRadius="5">
<Grid Margin="15">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Style="{DynamicResource TitleTextBlockStyle}" Text="B站录播姬"/>
<TextBlock Text="{Binding Recorder.Config.WorkDirectory,Mode=OneWay}" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis"/>
</StackPanel>
<Separator Grid.Row="1" Grid.ColumnSpan="2"/>
<ItemsControl Grid.Row="2" Grid.ColumnSpan="2" ItemsSource="{Binding Recorder, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,5,0,0">
<ui:PathIcon Data="M18.15,4.94C17.77,4.91 17.37,5 17,5.2L8.35,10.2C7.39,10.76 7.07,12 7.62,12.94L9.12,15.53C9.67,16.5 10.89,16.82 11.85,16.27L13.65,15.23C13.92,15.69 14.32,16.06 14.81,16.27V18.04C14.81,19.13 15.7,20 16.81,20H22V18.04H16.81V16.27C17.72,15.87 18.31,14.97 18.31,14C18.31,13.54 18.19,13.11 17.97,12.73L20.5,11.27C21.47,10.71 21.8,9.5 21.24,8.53L19.74,5.94C19.4,5.34 18.79,5 18.15,4.94M6.22,13.17L2,13.87L2.75,15.17L4.75,18.63L5.5,19.93L8.22,16.63L6.22,13.17Z"
Visibility="{Binding IsMonitoring,Converter={StaticResource BooleanToVisibilityConverter}}"
Foreground="DarkOrange" Width="15" ToolTip="监控中"/>
<ui:PathIcon Data="M12.5,5A7.5,7.5 0 0,0 5,12.5A7.5,7.5 0 0,0 12.5,20A7.5,7.5 0 0,0 20,12.5A7.5,7.5 0 0,0 12.5,5M7,10H9A1,1 0 0,1 10,11V12C10,12.5 9.62,12.9 9.14,12.97L10.31,15H9.15L8,13V15H7M12,10H14V11H12V12H14V13H12V14H14V15H12A1,1 0 0,1 11,14V11A1,1 0 0,1 12,10M16,10H18V11H16V14H18V15H16A1,1 0 0,1 15,14V11A1,1 0 0,1 16,10M8,11V12H9V11"
Visibility="{Binding IsRecording,Converter={StaticResource BooleanToVisibilityConverter}}"
Foreground="Red" Width="15" ToolTip="录制中" Margin="3,0"/>
<TextBlock Text="{Binding StreamerName, Mode=OneWay}"
ToolTip="{Binding StreamerName, Mode=OneWay}"
TextWrapping="NoWrap" TextTrimming="CharacterEllipsis"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</Border>
</UserControl>

View File

@ -0,0 +1,15 @@
using System.Windows.Controls;
namespace BililiveRecorder.WPF.Controls
{
/// <summary>
/// Interaction logic for TaskbarIconTrayPopup.xaml
/// </summary>
public partial class TaskbarIconTrayPopup : UserControl
{
public TaskbarIconTrayPopup()
{
InitializeComponent();
}
}
}

View File

@ -9,7 +9,7 @@
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:WorkDirectorySelectorDialog}"
PrimaryButtonText="确定"
IsPrimaryButtonEnabled="True"
DefaultButton="Primary"
CloseButtonText="退出">
<Grid>
<Grid.RowDefinitions>

View File

@ -0,0 +1,20 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace BililiveRecorder.WPF.Converters
{
internal class IsNullToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is null ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -1,19 +1,32 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using BililiveRecorder.Core;
namespace BililiveRecorder.WPF.Models
{
internal class RootModel : IDisposable
internal class RootModel : INotifyPropertyChanged, IDisposable
{
private bool disposedValue;
private IRecorder recorder;
public event PropertyChangedEventHandler PropertyChanged;
public LogModel Logs { get; } = new LogModel();
public IRecorder Recorder { get; internal set; }
public IRecorder Recorder { get => recorder; internal set => SetField(ref recorder, value); }
public RootModel()
{
}
protected virtual void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(field, value)) { return false; }
field = value; OnPropertyChanged(propertyName); return true;
}
protected virtual void Dispose(bool disposing)

View File

@ -15,6 +15,7 @@
Width="1000" Height="650"
MinHeight="400" MinWidth="340"
Closing="Window_Closing"
StateChanged="Window_StateChanged"
Title="录播姬">
<pages:RootPage x:Name="RootPage" CloseWindowRequested="RootPage_CloseWindowRequested"/>
<pages:RootPage x:Name="RootPage"/>
</Window>

View File

@ -2,6 +2,7 @@ using System;
using System.Threading;
using System.Windows;
using BililiveRecorder.WPF.Controls;
using Hardcodet.Wpf.TaskbarNotification;
using ModernWpf.Controls;
namespace BililiveRecorder.WPF
@ -17,12 +18,32 @@ namespace BililiveRecorder.WPF
Title = "录播姬 " + BuildInfo.Version + " " + BuildInfo.HeadShaShort;
BeforeWindowClose += NewMainWindow_BeforeWindowClose;
SingleInstance.NotificationReceived += SingleInstance_NotificationReceived;
SuperActivate += NewMainWindow_SuperActivate;
CloseWithoutConfirm += NewMainWindow_CloseWithoutConfirm;
SingleInstance.NotificationReceived += (sender, e) => SuperActivateAction();
}
private void SingleInstance_NotificationReceived(object sender, EventArgs e)
internal Action<string, string, BalloonIcon> ShowBalloonTipCallback { get; set; }
private void NewMainWindow_CloseWithoutConfirm(object sender, RoutedEventArgs e)
{
CloseWithoutConfirmAction();
}
internal void CloseWithoutConfirmAction()
{
CloseConfirmed = true;
Close();
}
private void NewMainWindow_SuperActivate(object sender, RoutedEventArgs e)
{
SuperActivateAction();
}
internal void SuperActivateAction()
{
Show();
WindowState = WindowState.Normal;
Topmost = true;
Activate();
@ -30,20 +51,83 @@ namespace BililiveRecorder.WPF
Focus();
}
private void Window_StateChanged(object sender, EventArgs e)
{
if (WindowState == WindowState.Minimized)
{
Hide();
ShowBalloonTipCallback?.Invoke("B质感录播姬", "录播姬已最小化到托盘,左键单击图标恢复界面", BalloonIcon.Info);
// RaiseEvent(new RoutedEventArgs(ShowBalloonTipEvent));
// RaiseEvent(new ShowBalloonTipRoutedEventArgs(ShowBalloonTipEvent)
// {
// Title = "B站录播姬",
// Message = "录播姬已最小化到托盘,左键单击图标恢复界面。",
// Symbol = BalloonIcon.Info
// });
}
}
#region Routed Events
public static readonly RoutedEvent BeforeWindowCloseEvent
= EventManager.RegisterRoutedEvent("BeforeWindowClose", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(NewMainWindow));
public event RoutedEventHandler BeforeWindowClose
{
add { AddHandler(BeforeWindowCloseEvent, value); }
remove { RemoveHandler(BeforeWindowCloseEvent, value); }
}
public static readonly RoutedEvent CloseWithoutConfirmEvent
= EventManager.RegisterRoutedEvent("CloseWithoutConfirm", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(NewMainWindow));
public event RoutedEventHandler CloseWithoutConfirm
{
add { AddHandler(CloseWithoutConfirmEvent, value); }
remove { RemoveHandler(CloseWithoutConfirmEvent, value); }
}
public static readonly RoutedEvent SuperActivateEvent
= EventManager.RegisterRoutedEvent("SuperActivate", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(NewMainWindow));
public event RoutedEventHandler SuperActivate
{
add { AddHandler(SuperActivateEvent, value); }
remove { RemoveHandler(SuperActivateEvent, value); }
}
public delegate void ShowBalloonTipRoutedEventHandler(object sender, ShowBalloonTipRoutedEventArgs e);
public static readonly RoutedEvent ShowBalloonTipEvent
= EventManager.RegisterRoutedEvent("ShowBalloonTip", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(NewMainWindow));
public event RoutedEventHandler ShowBalloonTip
{
add { AddHandler(ShowBalloonTipEvent, value); }
remove { RemoveHandler(ShowBalloonTipEvent, value); }
}
public class ShowBalloonTipRoutedEventArgs : RoutedEventArgs
{
public string Title { get; set; }
public string Message { get; set; }
public BalloonIcon Symbol { get; set; }
public ShowBalloonTipRoutedEventArgs() { }
public ShowBalloonTipRoutedEventArgs(RoutedEvent routedEvent) : base(routedEvent) { }
public ShowBalloonTipRoutedEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source) { }
}
#endregion
#region Confirm Close Window
private bool CloseConfirmed = false;
private readonly SemaphoreSlim CloseWindowSemaphoreSlim = new SemaphoreSlim(1, 1);
public event EventHandler BeforeWindowClose;
public bool PromptCloseConfirm { get; set; } = true;
private void NewMainWindow_BeforeWindowClose(object sender, EventArgs e)
{
RootPage?.Shutdown();
SingleInstance.Cleanup();
}
private async void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (PromptCloseConfirm && !CloseConfirmed)
@ -67,20 +151,12 @@ namespace BililiveRecorder.WPF
}
else
{
BeforeWindowClose?.Invoke(this, EventArgs.Empty);
RaiseEvent(new RoutedEventArgs(BeforeWindowCloseEvent));
return;
}
}
public void CloseWithoutConfirm()
{
CloseConfirmed = true;
Close();
}
#endregion
private void RootPage_CloseWindowRequested(object sender, EventArgs e)
{
CloseWithoutConfirm();
}
}
}

View File

@ -19,7 +19,7 @@
<RowDefinition/>
</Grid.RowDefinitions>
<ui:ThemeShadowChrome Margin="5">
<Border Background="{DynamicResource SystemControlBackgroundBaseLowBrush}"
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
BorderBrush="{DynamicResource SystemControlBackgroundAccentBrush}"
BorderThickness="1" CornerRadius="5">
<StackPanel Margin="10" Orientation="Vertical">
@ -55,7 +55,7 @@
</Border>
</ui:ThemeShadowChrome>
<ui:ThemeShadowChrome Grid.Row="1" IsShadowEnabled="True" Depth="10" Margin="5">
<Border Background="{DynamicResource SystemControlBackgroundBaseLowBrush}"
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
BorderBrush="{DynamicResource SystemControlBackgroundAccentBrush}"
BorderThickness="1" CornerRadius="5">
<ItemsControl x:Name="Log" ItemsSource="{Binding Mode=OneWay}" Margin="5" ToolTip="右键点击可以复制单行日志">

View File

@ -6,11 +6,14 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:local="clr-namespace:BililiveRecorder.WPF.Pages"
xmlns:mock="clr-namespace:BililiveRecorder.WPF.MockData"
xmlns:wpf="clr-namespace:BililiveRecorder.WPF"
xmlns:controls="clr-namespace:BililiveRecorder.WPF.Controls"
xmlns:models="clr-namespace:BililiveRecorder.WPF.Models"
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="600"
d:DataContext="{d:DesignInstance Type=models:RootModel,IsDesignTimeCreatable=True}"
Background="{DynamicResource SystemControlPageBackgroundAltHighBrush}">
Background="{DynamicResource SystemControlPageBackgroundAltHighBrush}"
wpf:NewMainWindow.BeforeWindowClose="UserControl_BeforeWindowClose"
>
<UserControl.Resources>
<Style x:Key="CascadeDataContextFrame" TargetType="{x:Type ui:Frame}">
<Setter Property="Template">
@ -42,35 +45,38 @@
</Setter>
</Style>
</UserControl.Resources>
<ui:NavigationView IsBackEnabled="False" IsBackButtonVisible="Collapsed"
<Grid>
<controls:TaskbarIconControl DataContext="{Binding}"/>
<ui:NavigationView IsBackEnabled="False" IsBackButtonVisible="Collapsed"
IsPaneOpen="False" OpenPaneLength="150"
IsSettingsVisible="False"
SelectionChanged="NavigationView_SelectionChanged"
>
<ui:NavigationView.MenuItems>
<ui:NavigationViewItem Content="房间列表" Tag="RoomListPage" x:Name="RoomListPageNavigationViewItem">
<ui:NavigationViewItem.Icon>
<ui:PathIcon Data="M12 5.69L17 10.19V18H15V12H9V18H7V10.19L12 5.69M12 3L2 12H5V20H11V14H13V20H19V12H22L12 3Z"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationView.MenuItems>
<ui:NavigationView.FooterMenuItems>
<ui:NavigationViewItem Content="高级设置" Tag="AdvancedSettingsPage" x:Name="AdvancedSettingsPageItem">
<ui:NavigationViewItem.Icon>
<ui:PathIcon Data="M15.9,18.45C17.25,18.45 18.35,17.35 18.35,16C18.35,14.65 17.25,13.55 15.9,13.55C14.54,13.55 13.45,14.65 13.45,16C13.45,17.35 14.54,18.45 15.9,18.45M21.1,16.68L22.58,17.84C22.71,17.95 22.75,18.13 22.66,18.29L21.26,20.71C21.17,20.86 21,20.92 20.83,20.86L19.09,20.16C18.73,20.44 18.33,20.67 17.91,20.85L17.64,22.7C17.62,22.87 17.47,23 17.3,23H14.5C14.32,23 14.18,22.87 14.15,22.7L13.89,20.85C13.46,20.67 13.07,20.44 12.71,20.16L10.96,20.86C10.81,20.92 10.62,20.86 10.54,20.71L9.14,18.29C9.05,18.13 9.09,17.95 9.22,17.84L10.7,16.68L10.65,16L10.7,15.31L9.22,14.16C9.09,14.05 9.05,13.86 9.14,13.71L10.54,11.29C10.62,11.13 10.81,11.07 10.96,11.13L12.71,11.84C13.07,11.56 13.46,11.32 13.89,11.15L14.15,9.29C14.18,9.13 14.32,9 14.5,9H17.3C17.47,9 17.62,9.13 17.64,9.29L17.91,11.15C18.33,11.32 18.73,11.56 19.09,11.84L20.83,11.13C21,11.07 21.17,11.13 21.26,11.29L22.66,13.71C22.75,13.86 22.71,14.05 22.58,14.16L21.1,15.31L21.15,16L21.1,16.68M6.69,8.07C7.56,8.07 8.26,7.37 8.26,6.5C8.26,5.63 7.56,4.92 6.69,4.92A1.58,1.58 0 0,0 5.11,6.5C5.11,7.37 5.82,8.07 6.69,8.07M10.03,6.94L11,7.68C11.07,7.75 11.09,7.87 11.03,7.97L10.13,9.53C10.08,9.63 9.96,9.67 9.86,9.63L8.74,9.18L8,9.62L7.81,10.81C7.79,10.92 7.7,11 7.59,11H5.79C5.67,11 5.58,10.92 5.56,10.81L5.4,9.62L4.64,9.18L3.5,9.63C3.41,9.67 3.3,9.63 3.24,9.53L2.34,7.97C2.28,7.87 2.31,7.75 2.39,7.68L3.34,6.94L3.31,6.5L3.34,6.06L2.39,5.32C2.31,5.25 2.28,5.13 2.34,5.03L3.24,3.47C3.3,3.37 3.41,3.33 3.5,3.37L4.63,3.82L5.4,3.38L5.56,2.19C5.58,2.08 5.67,2 5.79,2H7.59C7.7,2 7.79,2.08 7.81,2.19L8,3.38L8.74,3.82L9.86,3.37C9.96,3.33 10.08,3.37 10.13,3.47L11.03,5.03C11.09,5.13 11.07,5.25 11,5.32L10.03,6.06L10.06,6.5L10.03,6.94Z"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Content="日志" Tag="LogPage">
<ui:NavigationViewItem.Icon>
<ui:PathIcon Data="M9 3C5.69 3 3.14 5.69 3 9V21H12V13.46C13.1 14.45 14.5 15 16 15C19.31 15 22 12.31 22 9C22 5.69 19.31 3 16 3H9M9 5H11.54C10.55 6.1 10 7.5 10 9V12H9V13H10V19H5V13H6V12H5V9C5 6.79 6.79 5 9 5M16 5C18.21 5 20 6.79 20 9C20 11.21 18.21 13 16 13C13.79 13 12 11.21 12 9C12 6.79 13.79 5 16 5M16 7.25C15.03 7.25 14.25 8.03 14.25 9C14.25 9.97 15.03 10.75 16 10.75C16.97 10.75 17.75 9.97 17.75 9C17.75 8.03 16.97 7.25 16 7.25M7 12V13H8V12H7Z"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Content="设置" Tag="SettingsPage" MouseRightButtonUp="NavigationViewItem_MouseRightButtonUp">
<ui:NavigationViewItem.Icon>
<ui:PathIcon Data="M12,8A4,4 0 0,1 16,12A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8M12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12A2,2 0 0,0 12,10M10,22C9.75,22 9.54,21.82 9.5,21.58L9.13,18.93C8.5,18.68 7.96,18.34 7.44,17.94L4.95,18.95C4.73,19.03 4.46,18.95 4.34,18.73L2.34,15.27C2.21,15.05 2.27,14.78 2.46,14.63L4.57,12.97L4.5,12L4.57,11L2.46,9.37C2.27,9.22 2.21,8.95 2.34,8.73L4.34,5.27C4.46,5.05 4.73,4.96 4.95,5.05L7.44,6.05C7.96,5.66 8.5,5.32 9.13,5.07L9.5,2.42C9.54,2.18 9.75,2 10,2H14C14.25,2 14.46,2.18 14.5,2.42L14.87,5.07C15.5,5.32 16.04,5.66 16.56,6.05L19.05,5.05C19.27,4.96 19.54,5.05 19.66,5.27L21.66,8.73C21.79,8.95 21.73,9.22 21.54,9.37L19.43,11L19.5,12L19.43,13L21.54,14.63C21.73,14.78 21.79,15.05 21.66,15.27L19.66,18.73C19.54,18.95 19.27,19.04 19.05,18.95L16.56,17.95C16.04,18.34 15.5,18.68 14.87,18.93L14.5,21.58C14.46,21.82 14.25,22 14,22H10M11.25,4L10.88,6.61C9.68,6.86 8.62,7.5 7.85,8.39L5.44,7.35L4.69,8.65L6.8,10.2C6.4,11.37 6.4,12.64 6.8,13.8L4.68,15.36L5.43,16.66L7.86,15.62C8.63,16.5 9.68,17.14 10.87,17.38L11.24,20H12.76L13.13,17.39C14.32,17.14 15.37,16.5 16.14,15.62L18.57,16.66L19.32,15.36L17.2,13.81C17.6,12.64 17.6,11.37 17.2,10.2L19.31,8.65L18.56,7.35L16.15,8.39C15.38,7.5 14.32,6.86 13.12,6.62L12.75,4H11.25Z"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationView.FooterMenuItems>
<ui:Frame x:Name="MainFrame" Style="{DynamicResource CascadeDataContextFrame}" />
</ui:NavigationView>
<ui:NavigationView.MenuItems>
<ui:NavigationViewItem Content="房间列表" Tag="RoomListPage" x:Name="RoomListPageNavigationViewItem">
<ui:NavigationViewItem.Icon>
<ui:PathIcon Data="M12 5.69L17 10.19V18H15V12H9V18H7V10.19L12 5.69M12 3L2 12H5V20H11V14H13V20H19V12H22L12 3Z"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationView.MenuItems>
<ui:NavigationView.FooterMenuItems>
<ui:NavigationViewItem Content="高级设置" Tag="AdvancedSettingsPage" x:Name="AdvancedSettingsPageItem">
<ui:NavigationViewItem.Icon>
<ui:PathIcon Data="M15.9,18.45C17.25,18.45 18.35,17.35 18.35,16C18.35,14.65 17.25,13.55 15.9,13.55C14.54,13.55 13.45,14.65 13.45,16C13.45,17.35 14.54,18.45 15.9,18.45M21.1,16.68L22.58,17.84C22.71,17.95 22.75,18.13 22.66,18.29L21.26,20.71C21.17,20.86 21,20.92 20.83,20.86L19.09,20.16C18.73,20.44 18.33,20.67 17.91,20.85L17.64,22.7C17.62,22.87 17.47,23 17.3,23H14.5C14.32,23 14.18,22.87 14.15,22.7L13.89,20.85C13.46,20.67 13.07,20.44 12.71,20.16L10.96,20.86C10.81,20.92 10.62,20.86 10.54,20.71L9.14,18.29C9.05,18.13 9.09,17.95 9.22,17.84L10.7,16.68L10.65,16L10.7,15.31L9.22,14.16C9.09,14.05 9.05,13.86 9.14,13.71L10.54,11.29C10.62,11.13 10.81,11.07 10.96,11.13L12.71,11.84C13.07,11.56 13.46,11.32 13.89,11.15L14.15,9.29C14.18,9.13 14.32,9 14.5,9H17.3C17.47,9 17.62,9.13 17.64,9.29L17.91,11.15C18.33,11.32 18.73,11.56 19.09,11.84L20.83,11.13C21,11.07 21.17,11.13 21.26,11.29L22.66,13.71C22.75,13.86 22.71,14.05 22.58,14.16L21.1,15.31L21.15,16L21.1,16.68M6.69,8.07C7.56,8.07 8.26,7.37 8.26,6.5C8.26,5.63 7.56,4.92 6.69,4.92A1.58,1.58 0 0,0 5.11,6.5C5.11,7.37 5.82,8.07 6.69,8.07M10.03,6.94L11,7.68C11.07,7.75 11.09,7.87 11.03,7.97L10.13,9.53C10.08,9.63 9.96,9.67 9.86,9.63L8.74,9.18L8,9.62L7.81,10.81C7.79,10.92 7.7,11 7.59,11H5.79C5.67,11 5.58,10.92 5.56,10.81L5.4,9.62L4.64,9.18L3.5,9.63C3.41,9.67 3.3,9.63 3.24,9.53L2.34,7.97C2.28,7.87 2.31,7.75 2.39,7.68L3.34,6.94L3.31,6.5L3.34,6.06L2.39,5.32C2.31,5.25 2.28,5.13 2.34,5.03L3.24,3.47C3.3,3.37 3.41,3.33 3.5,3.37L4.63,3.82L5.4,3.38L5.56,2.19C5.58,2.08 5.67,2 5.79,2H7.59C7.7,2 7.79,2.08 7.81,2.19L8,3.38L8.74,3.82L9.86,3.37C9.96,3.33 10.08,3.37 10.13,3.47L11.03,5.03C11.09,5.13 11.07,5.25 11,5.32L10.03,6.06L10.06,6.5L10.03,6.94Z"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Content="日志" Tag="LogPage">
<ui:NavigationViewItem.Icon>
<ui:PathIcon Data="M9 3C5.69 3 3.14 5.69 3 9V21H12V13.46C13.1 14.45 14.5 15 16 15C19.31 15 22 12.31 22 9C22 5.69 19.31 3 16 3H9M9 5H11.54C10.55 6.1 10 7.5 10 9V12H9V13H10V19H5V13H6V12H5V9C5 6.79 6.79 5 9 5M16 5C18.21 5 20 6.79 20 9C20 11.21 18.21 13 16 13C13.79 13 12 11.21 12 9C12 6.79 13.79 5 16 5M16 7.25C15.03 7.25 14.25 8.03 14.25 9C14.25 9.97 15.03 10.75 16 10.75C16.97 10.75 17.75 9.97 17.75 9C17.75 8.03 16.97 7.25 16 7.25M7 12V13H8V12H7Z"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Content="设置" Tag="SettingsPage" MouseRightButtonUp="NavigationViewItem_MouseRightButtonUp">
<ui:NavigationViewItem.Icon>
<ui:PathIcon Data="M12,8A4,4 0 0,1 16,12A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8M12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12A2,2 0 0,0 12,10M10,22C9.75,22 9.54,21.82 9.5,21.58L9.13,18.93C8.5,18.68 7.96,18.34 7.44,17.94L4.95,18.95C4.73,19.03 4.46,18.95 4.34,18.73L2.34,15.27C2.21,15.05 2.27,14.78 2.46,14.63L4.57,12.97L4.5,12L4.57,11L2.46,9.37C2.27,9.22 2.21,8.95 2.34,8.73L4.34,5.27C4.46,5.05 4.73,4.96 4.95,5.05L7.44,6.05C7.96,5.66 8.5,5.32 9.13,5.07L9.5,2.42C9.54,2.18 9.75,2 10,2H14C14.25,2 14.46,2.18 14.5,2.42L14.87,5.07C15.5,5.32 16.04,5.66 16.56,6.05L19.05,5.05C19.27,4.96 19.54,5.05 19.66,5.27L21.66,8.73C21.79,8.95 21.73,9.22 21.54,9.37L19.43,11L19.5,12L19.43,13L21.54,14.63C21.73,14.78 21.79,15.05 21.66,15.27L19.66,18.73C19.54,18.95 19.27,19.04 19.05,18.95L16.56,17.95C16.04,18.34 15.5,18.68 14.87,18.93L14.5,21.58C14.46,21.82 14.25,22 14,22H10M11.25,4L10.88,6.61C9.68,6.86 8.62,7.5 7.85,8.39L5.44,7.35L4.69,8.65L6.8,10.2C6.4,11.37 6.4,12.64 6.8,13.8L4.68,15.36L5.43,16.66L7.86,15.62C8.63,16.5 9.68,17.14 10.87,17.38L11.24,20H12.76L13.13,17.39C14.32,17.14 15.37,16.5 16.14,15.62L18.57,16.66L19.32,15.36L17.2,13.81C17.6,12.64 17.6,11.37 17.2,10.2L19.31,8.65L18.56,7.35L16.15,8.39C15.38,7.5 14.32,6.86 13.12,6.62L12.75,4H11.25Z"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationView.FooterMenuItems>
<ui:Frame x:Name="MainFrame" Style="{DynamicResource CascadeDataContextFrame}" />
</ui:NavigationView>
</Grid>
</UserControl>

View File

@ -31,8 +31,6 @@ namespace BililiveRecorder.WPF.Pages
internal RootModel Model { get; private set; }
public event EventHandler CloseWindowRequested;
public RootPage()
{
void AddType(Type t) => PageMap.Add(t.Name, t);
@ -56,11 +54,6 @@ namespace BililiveRecorder.WPF.Pages
Loaded += RootPage_Loaded;
}
public void Shutdown()
{
Model.Dispose();
}
private async void RootPage_Loaded(object sender, RoutedEventArgs e)
{
bool first_time = true;
@ -102,7 +95,7 @@ namespace BililiveRecorder.WPF.Pages
var result = await w.ShowAsync();
if (result != ContentDialogResult.Primary)
{
CloseWindowRequested?.Invoke(this, EventArgs.Empty);
RaiseEvent(new RoutedEventArgs(NewMainWindow.CloseWithoutConfirmEvent));
return;
}
@ -151,7 +144,7 @@ namespace BililiveRecorder.WPF.Pages
}
else
{
CloseWindowRequested?.Invoke(this, EventArgs.Empty);
RaiseEvent(new RoutedEventArgs(NewMainWindow.CloseWithoutConfirmEvent));
return;
}
}
@ -184,5 +177,11 @@ namespace BililiveRecorder.WPF.Pages
AdvancedSettingsPageItem.Visibility = AdvancedSettingsPageItem.Visibility != Visibility.Visible ? Visibility.Visible : Visibility.Hidden;
}
}
private void UserControl_BeforeWindowClose(object sender, RoutedEventArgs e)
{
Model.Dispose();
SingleInstance.Cleanup();
}
}
}