refactor:迁移设置
This commit is contained in:
@@ -1,17 +1,194 @@
|
||||
<ui:Page
|
||||
x:Class="Ink_Canvas.Windows.SettingsViews.Pages.AboutPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
|
||||
Title="关于"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<StackPanel Margin="24">
|
||||
<TextBlock Text="关于 InkCanvasForClass" Style="{DynamicResource TitleTextBlockStyle}" Margin="0,0,0,16" />
|
||||
<TextBlock Text="这里是关于页面" Style="{DynamicResource BodyTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ui:Page>
|
||||
<ui:Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.AboutPage"
|
||||
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:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
|
||||
xmlns:i18n="clr-namespace:Ink_Canvas.MarkupExtensions"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d"
|
||||
|
||||
Title="关于">
|
||||
|
||||
<ScrollViewer PanningMode="VerticalFirst">
|
||||
<Grid Margin="59,0,59,0">
|
||||
<FrameworkElement.Resources>
|
||||
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
|
||||
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
|
||||
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
|
||||
TargetType="TextBlock">
|
||||
<Style.Setters>
|
||||
<Setter Property="Margin" Value="1,30,0,6" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
<DataTemplate x:Key="DeveloperAvatarTemplate">
|
||||
<ikw:SimpleStackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<Image Source="{Binding AvatarPath}"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Center"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" Width="96" Height="96" Margin="0,0,0,6">
|
||||
<Image.Clip>
|
||||
<EllipseGeometry Center="48,48" RadiusX="48" RadiusY="48" />
|
||||
</Image.Clip>
|
||||
</Image>
|
||||
<TextBlock Text="{Binding Name}" HorizontalAlignment="Center" FontSize="18" FontWeight="Bold" Foreground="#fde047" />
|
||||
<TextBlock Text="{Binding Role}" HorizontalAlignment="Center" FontSize="12" Foreground="White" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="ContributorAvatarTemplate">
|
||||
<ikw:SimpleStackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<Image Source="{Binding AvatarPath}"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Center"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" Width="48" Height="48" Margin="0,0,0,4">
|
||||
<Image.Clip>
|
||||
<EllipseGeometry Center="24,24" RadiusX="24" RadiusY="24" />
|
||||
</Image.Clip>
|
||||
</Image>
|
||||
<TextBlock Text="{Binding Name}" HorizontalAlignment="Center" FontSize="12" Foreground="White" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</DataTemplate>
|
||||
</FrameworkElement.Resources>
|
||||
<Grid>
|
||||
<ikw:SimpleStackPanel MaxWidth="1000"
|
||||
HorizontalAlignment="Stretch"
|
||||
Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="{i18n:I18n Key=About_Title}" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=About_VersionLabel}">
|
||||
<ui:SettingsCard.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Info}" />
|
||||
</ui:SettingsCard.HeaderIcon>
|
||||
<TextBlock x:Name="AppVersionTextBlock" Text="1.X.X.X" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
</ui:SettingsCard>
|
||||
|
||||
<ui:SettingsExpander Header="{i18n:I18n Key=About_DeviceInfo}">
|
||||
<ui:SettingsExpander.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Devices}" />
|
||||
</ui:SettingsExpander.HeaderIcon>
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=About_DeviceIdLabel}">
|
||||
<TextBlock x:Name="DeviceIdTextBlock" Text="{i18n:I18n Key=About_DeviceInfo_Loading}" />
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=About_UsageFrequencyLabel}">
|
||||
<TextBlock x:Name="UsageFrequencyTextBlock" Text="{i18n:I18n Key=About_DeviceInfo_Loading}" />
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=About_UpdatePriorityLabel}">
|
||||
<TextBlock x:Name="UpdatePriorityTextBlock" Text="{i18n:I18n Key=About_DeviceInfo_Loading}" />
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=About_LaunchCountLabel}">
|
||||
<TextBlock x:Name="LaunchCountTextBlock" Text="{i18n:I18n Key=About_DeviceInfo_Loading}" />
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=About_TotalUsageLabel}">
|
||||
<TextBlock x:Name="TotalUsageTextBlock" Text="{i18n:I18n Key=About_DeviceInfo_Loading}" />
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="">
|
||||
<Button x:Name="RefreshDeviceInfoButton" Content="{i18n:I18n Key=About_RefreshDeviceInfo}"
|
||||
Click="RefreshDeviceInfo_Click" />
|
||||
</ui:SettingsCard>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{i18n:I18n Key=About_PrivacyAndTelemetry}">
|
||||
<ui:SettingsExpander.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Shield}" />
|
||||
</ui:SettingsExpander.HeaderIcon>
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsCard ContentAlignment="Left">
|
||||
<CheckBox x:Name="CheckBoxTelemetryPrivacyAccepted"
|
||||
Content="{i18n:I18n Key=About_PrivacyAgreement}"
|
||||
Checked="CheckBoxTelemetryPrivacyAccepted_Checked"
|
||||
Unchecked="CheckBoxTelemetryPrivacyAccepted_Checked" />
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=About_TelemetryLabel}">
|
||||
<ComboBox x:Name="ComboBoxTelemetryUploadLevel"
|
||||
SelectionChanged="ComboBoxTelemetryUploadLevel_SelectionChanged">
|
||||
<ComboBoxItem Tag="0" Content="{i18n:I18n Key=About_Telemetry_Off}" />
|
||||
<ComboBoxItem Tag="1" Content="{i18n:I18n Key=About_Telemetry_Basic}" />
|
||||
<ComboBoxItem Tag="2" Content="{i18n:I18n Key=About_Telemetry_Optional}" />
|
||||
</ComboBox>
|
||||
</ui:SettingsCard>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<Border Background="{DynamicResource {x:Static ui:ThemeKeys.LayerFillColorDefaultBrushKey}}"
|
||||
BorderBrush="{DynamicResource {x:Static ui:ThemeKeys.CardStrokeColorDefaultBrushKey}}"
|
||||
CornerRadius="4" BorderThickness="1" Padding="12,10" TextElement.FontSize="14">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="8"
|
||||
TextElement.Foreground="{DynamicResource {x:Static ui:ThemeKeys.AccentTextFillColorPrimaryBrushKey}}"
|
||||
Margin="0,3,0,0">
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Info}" FontSize="24"/>
|
||||
<TextBlock FontSize="16" VerticalAlignment="Center" FontWeight="SemiBold"
|
||||
Text="{i18n:I18n Key=About_LicenseTitle}" />
|
||||
</ikw:SimpleStackPanel>
|
||||
|
||||
<ikw:SimpleStackPanel Orientation="Vertical" Spacing="12" Grid.Row="1" Margin="5,10">
|
||||
<FrameworkElement.Resources>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="LineHeight" Value="21"/>
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
</Style>
|
||||
</FrameworkElement.Resources>
|
||||
|
||||
<TextBlock Text="GNU General Public License v3.0" FontSize="20" FontWeight="Bold"/>
|
||||
<TextBlock Text="{i18n:I18n Key=About_LicenseBody}" FontSize="11"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
<Separator Opacity="0.2"/>
|
||||
</ikw:SimpleStackPanel>
|
||||
|
||||
<ikw:SimpleStackPanel Grid.Row="2" Orientation="Horizontal" Spacing="10">
|
||||
<ui:HyperlinkButton Content="ICC CE" NavigateUri="https://github.com/InkCanvasForClass/community/"/>
|
||||
<ui:HyperlinkButton Content="ICA" NavigateUri="https://github.com/ChangSakura/Ink-Canvas"/>
|
||||
<ui:HyperlinkButton Content="Ink Canvas" NavigateUri="https://github.com/WXRIW/Ink-Canvas"/>
|
||||
</ikw:SimpleStackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="{i18n:I18n Key=About_DevelopersLabel}" />
|
||||
|
||||
<ItemsControl x:Name="DeveloperItemsControl"
|
||||
ItemTemplate="{StaticResource DeveloperAvatarTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" ItemWidth="130" Margin="0,0,0,8" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
|
||||
<Separator Margin="0,8" />
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="{i18n:I18n Key=About_ThanksContributors}" />
|
||||
|
||||
<ItemsControl x:Name="ContributorItemsControl"
|
||||
ItemTemplate="{StaticResource ContributorAvatarTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" ItemWidth="96" Margin="0,0,0,8" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
|
||||
<Separator Margin="0,8" />
|
||||
|
||||
<ikw:SimpleStackPanel Spacing="3" Orientation="Vertical" Margin="0,0,0,24">
|
||||
<TextBlock Text="{i18n:I18n Key=About_Copyright}" FontWeight="Bold" TextWrapping="Wrap" />
|
||||
<TextBlock Text="{i18n:I18n Key=About_OpenSourceSlogan}" FontWeight="Bold"
|
||||
TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
</ikw:SimpleStackPanel>
|
||||
|
||||
</ikw:SimpleStackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</ui:Page>
|
||||
|
||||
@@ -1,12 +1,424 @@
|
||||
using iNKORE.UI.WPF.Modern.Controls;
|
||||
using Ink_Canvas.Helpers;
|
||||
using Ink_Canvas.Windows.SettingsViews.Helpers;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Ink_Canvas.Windows.SettingsViews.Pages
|
||||
{
|
||||
public partial class AboutPage : Page
|
||||
public class AvatarItem
|
||||
{
|
||||
public string AvatarPath { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Role { get; set; }
|
||||
}
|
||||
|
||||
public partial class AboutPage : iNKORE.UI.WPF.Modern.Controls.Page
|
||||
{
|
||||
private bool _isLoaded = false;
|
||||
private bool _isChangingTelemetryInternally;
|
||||
private bool _isChangingTelemetryPrivacyInternally;
|
||||
private DispatcherTimer _usageRefreshTimer;
|
||||
private long _savedTotalSeconds;
|
||||
private DateTime _sessionStartTime;
|
||||
|
||||
public AboutPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += AboutPage_Loaded;
|
||||
Unloaded += AboutPage_Unloaded;
|
||||
InitializeAvatarData();
|
||||
}
|
||||
|
||||
private void InitializeAvatarData()
|
||||
{
|
||||
var developers = new ObservableCollection<AvatarItem>
|
||||
{
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/CJKmkp.jpg", Name = "CJK_mkp", Role = LocalizationHelper.GetString("About_Dev_ICCCE") },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/dubi906w.jpg", Name = "Dubi906w", Role = LocalizationHelper.GetString("About_Dev_ICC") },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/ChangSakura.png", Name = "ChangSakura", Role = LocalizationHelper.GetString("About_Dev_ICA") },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/WXRIW.png", Name = "WXRIW", Role = LocalizationHelper.GetString("About_Dev_InkCanvas") }
|
||||
};
|
||||
|
||||
var contributors = new ObservableCollection<AvatarItem>
|
||||
{
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/RaspberryKan.jpg", Name = "Raspberry Kan" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/kengwang.png", Name = "Kengwang" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/jiajiaxd.jpg", Name = "Charles Jia" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/clover-yan.png", Name = "clover_yan" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/NetheriteBowl.png", Name = "Netherite_Bowl" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/NotYoojun.png", Name = "Yoojun Zhou" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/yuwenhui2020.png", Name = "YuWenHui2020" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/STBBRD.png", Name = "ZongziTEK" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/aaaaaaccd.jpg", Name = "Aesthed" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/wwei.png", Name = "Wei" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/Alan-CRL.png", Name = "Alan-CRL" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/PrefacedCorg.jpg", Name = "PrefacedCorg" },
|
||||
new AvatarItem { AvatarPath = "/Resources/DeveloperAvatars/PANDA-JSR.jpg", Name = "PANDA-JSR" }
|
||||
};
|
||||
|
||||
DeveloperItemsControl.ItemsSource = developers;
|
||||
ContributorItemsControl.ItemsSource = contributors;
|
||||
}
|
||||
|
||||
private void AboutPage_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LoadSettings();
|
||||
_isLoaded = true;
|
||||
|
||||
if (_usageRefreshTimer == null)
|
||||
{
|
||||
_usageRefreshTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
|
||||
_usageRefreshTimer.Tick += UsageRefreshTimer_Tick;
|
||||
}
|
||||
_usageRefreshTimer.Start();
|
||||
}
|
||||
|
||||
private void AboutPage_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_usageRefreshTimer != null)
|
||||
{
|
||||
_usageRefreshTimer.Stop();
|
||||
_usageRefreshTimer.Tick -= UsageRefreshTimer_Tick;
|
||||
_usageRefreshTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void UsageRefreshTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
long currentSessionSeconds = (long)(DateTime.Now - _sessionStartTime).TotalSeconds;
|
||||
TotalUsageTextBlock.Text = DeviceIdentifier.FormatDuration(_savedTotalSeconds + currentSessionSeconds);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void LoadSettings()
|
||||
{
|
||||
_isLoaded = false;
|
||||
|
||||
try
|
||||
{
|
||||
AppVersionTextBlock.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
|
||||
var settings = SettingsManager.Settings;
|
||||
if (settings?.Startup != null)
|
||||
{
|
||||
int idx = 0;
|
||||
switch (settings.Startup.TelemetryUploadLevel)
|
||||
{
|
||||
case TelemetryUploadLevel.None:
|
||||
idx = 0;
|
||||
break;
|
||||
case TelemetryUploadLevel.Basic:
|
||||
idx = 1;
|
||||
break;
|
||||
case TelemetryUploadLevel.Extended:
|
||||
idx = 2;
|
||||
break;
|
||||
default:
|
||||
idx = 0;
|
||||
break;
|
||||
}
|
||||
ComboBoxTelemetryUploadLevel.SelectedIndex = idx;
|
||||
CheckBoxTelemetryPrivacyAccepted.IsChecked = settings.Startup.HasAcceptedTelemetryPrivacy;
|
||||
}
|
||||
|
||||
RefreshDeviceInfo();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"加载关于页面设置时出错: {ex.Message}");
|
||||
}
|
||||
|
||||
_isLoaded = true;
|
||||
}
|
||||
|
||||
private void RefreshDeviceInfo_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RefreshDeviceInfo();
|
||||
}
|
||||
|
||||
private void RefreshDeviceInfo()
|
||||
{
|
||||
try
|
||||
{
|
||||
string deviceId = DeviceIdentifier.GetDeviceId();
|
||||
DeviceIdTextBlock.Text = deviceId;
|
||||
|
||||
var usageFrequency = DeviceIdentifier.GetUsageFrequency();
|
||||
string frequencyText;
|
||||
switch (usageFrequency)
|
||||
{
|
||||
case DeviceIdentifier.UsageFrequency.High:
|
||||
frequencyText = "高频用户";
|
||||
break;
|
||||
case DeviceIdentifier.UsageFrequency.Medium:
|
||||
frequencyText = "中频用户";
|
||||
break;
|
||||
case DeviceIdentifier.UsageFrequency.Low:
|
||||
frequencyText = "低频用户";
|
||||
break;
|
||||
default:
|
||||
frequencyText = "未知";
|
||||
break;
|
||||
}
|
||||
UsageFrequencyTextBlock.Text = frequencyText;
|
||||
|
||||
var updatePriority = DeviceIdentifier.GetUpdatePriority();
|
||||
string priorityText;
|
||||
switch (updatePriority)
|
||||
{
|
||||
case DeviceIdentifier.UpdatePriority.High:
|
||||
priorityText = "高优先级(优先推送更新)";
|
||||
break;
|
||||
case DeviceIdentifier.UpdatePriority.Medium:
|
||||
priorityText = "中优先级(正常推送更新)";
|
||||
break;
|
||||
case DeviceIdentifier.UpdatePriority.Low:
|
||||
priorityText = "低优先级(延迟推送更新)";
|
||||
break;
|
||||
default:
|
||||
priorityText = "未知";
|
||||
break;
|
||||
}
|
||||
UpdatePriorityTextBlock.Text = priorityText;
|
||||
|
||||
var (launchCount, totalSeconds, avgSessionSeconds, _) = DeviceIdentifier.GetUsageStats();
|
||||
_savedTotalSeconds = totalSeconds;
|
||||
_sessionStartTime = DateTime.Now;
|
||||
LaunchCountTextBlock.Text = launchCount.ToString();
|
||||
TotalUsageTextBlock.Text = DeviceIdentifier.FormatDuration(totalSeconds);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"刷新设备信息失败: {ex.Message}", LogHelper.LogType.Error);
|
||||
DeviceIdTextBlock.Text = "获取失败";
|
||||
UsageFrequencyTextBlock.Text = "获取失败";
|
||||
UpdatePriorityTextBlock.Text = "获取失败";
|
||||
LaunchCountTextBlock.Text = "获取失败";
|
||||
TotalUsageTextBlock.Text = "获取失败";
|
||||
}
|
||||
}
|
||||
|
||||
private void ComboBoxTelemetryUploadLevel_SelectionChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
if (_isChangingTelemetryInternally) return;
|
||||
var oldLevel = SettingsManager.Settings.Startup.TelemetryUploadLevel;
|
||||
var item = ComboBoxTelemetryUploadLevel?.SelectedItem as ComboBoxItem;
|
||||
if (item == null) return;
|
||||
|
||||
var tag = item.Tag?.ToString() ?? "0";
|
||||
var newLevel = TelemetryUploadLevel.None;
|
||||
switch (tag)
|
||||
{
|
||||
case "1":
|
||||
newLevel = TelemetryUploadLevel.Basic;
|
||||
break;
|
||||
case "2":
|
||||
newLevel = TelemetryUploadLevel.Extended;
|
||||
break;
|
||||
default:
|
||||
newLevel = TelemetryUploadLevel.None;
|
||||
break;
|
||||
}
|
||||
|
||||
if (newLevel == TelemetryUploadLevel.None &&
|
||||
oldLevel != TelemetryUploadLevel.None &&
|
||||
SettingsManager.Settings.Startup.UpdateChannel != UpdateChannel.Release)
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
"关闭匿名使用数据上传后,将无法继续使用预览/测试通道,系统会自动切换回正式通道(Release)。\n\n是否确认关闭?",
|
||||
"确认关闭遥测",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Warning);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
{
|
||||
_isChangingTelemetryInternally = true;
|
||||
try
|
||||
{
|
||||
int idx = 0;
|
||||
switch (oldLevel)
|
||||
{
|
||||
case TelemetryUploadLevel.Basic:
|
||||
idx = 1;
|
||||
break;
|
||||
case TelemetryUploadLevel.Extended:
|
||||
idx = 2;
|
||||
break;
|
||||
default:
|
||||
idx = 0;
|
||||
break;
|
||||
}
|
||||
ComboBoxTelemetryUploadLevel.SelectedIndex = idx;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isChangingTelemetryInternally = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsManager.Settings.Startup.UpdateChannel = UpdateChannel.Release;
|
||||
DeviceIdentifier.UpdateUsageChannel(UpdateChannel.Release);
|
||||
}
|
||||
|
||||
if (newLevel != TelemetryUploadLevel.None && !SettingsManager.Settings.Startup.HasAcceptedTelemetryPrivacy)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"在开启匿名使用数据上传前,请先阅读并勾选上方的隐私说明。",
|
||||
"需要同意隐私说明",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Warning);
|
||||
|
||||
_isChangingTelemetryInternally = true;
|
||||
try
|
||||
{
|
||||
SettingsManager.Settings.Startup.TelemetryUploadLevel = TelemetryUploadLevel.None;
|
||||
if (ComboBoxTelemetryUploadLevel != null)
|
||||
{
|
||||
ComboBoxTelemetryUploadLevel.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isChangingTelemetryInternally = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsManager.Settings.Startup.TelemetryUploadLevel = newLevel;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void CheckBoxTelemetryPrivacyAccepted_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
if (_isChangingTelemetryPrivacyInternally) return;
|
||||
|
||||
bool isChecked = CheckBoxTelemetryPrivacyAccepted.IsChecked == true;
|
||||
|
||||
if (isChecked)
|
||||
{
|
||||
if (!PrivacyFileExists())
|
||||
{
|
||||
MessageBox.Show(
|
||||
"未找到隐私说明文件(privacy / privacy.txt),暂时无法启用匿名使用数据上传。",
|
||||
"隐私说明缺失",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Warning);
|
||||
|
||||
_isChangingTelemetryPrivacyInternally = true;
|
||||
try
|
||||
{
|
||||
CheckBoxTelemetryPrivacyAccepted.IsChecked = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isChangingTelemetryPrivacyInternally = false;
|
||||
}
|
||||
|
||||
SettingsManager.Settings.Startup.HasAcceptedTelemetryPrivacy = false;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
return;
|
||||
}
|
||||
|
||||
var privacyWindow = new PrivacyAgreementWindow();
|
||||
bool? dialogResult = privacyWindow.ShowDialog();
|
||||
|
||||
if (dialogResult == true && privacyWindow.UserAccepted)
|
||||
{
|
||||
SettingsManager.Settings.Startup.HasAcceptedTelemetryPrivacy = true;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
_isChangingTelemetryPrivacyInternally = true;
|
||||
try
|
||||
{
|
||||
CheckBoxTelemetryPrivacyAccepted.IsChecked = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isChangingTelemetryPrivacyInternally = false;
|
||||
}
|
||||
|
||||
SettingsManager.Settings.Startup.HasAcceptedTelemetryPrivacy = false;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
"取消同意隐私说明后,将关闭匿名使用数据上传,并切回正式通道(Release)。\n\n是否确认?",
|
||||
"确认取消隐私同意",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Warning);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
{
|
||||
_isChangingTelemetryPrivacyInternally = true;
|
||||
try
|
||||
{
|
||||
CheckBoxTelemetryPrivacyAccepted.IsChecked = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isChangingTelemetryPrivacyInternally = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_isChangingTelemetryInternally = true;
|
||||
try
|
||||
{
|
||||
SettingsManager.Settings.Startup.TelemetryUploadLevel = TelemetryUploadLevel.None;
|
||||
if (ComboBoxTelemetryUploadLevel != null)
|
||||
{
|
||||
ComboBoxTelemetryUploadLevel.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isChangingTelemetryInternally = false;
|
||||
}
|
||||
|
||||
if (SettingsManager.Settings.Startup.UpdateChannel != UpdateChannel.Release)
|
||||
{
|
||||
SettingsManager.Settings.Startup.UpdateChannel = UpdateChannel.Release;
|
||||
DeviceIdentifier.UpdateUsageChannel(UpdateChannel.Release);
|
||||
}
|
||||
|
||||
SettingsManager.Settings.Startup.HasAcceptedTelemetryPrivacy = false;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool PrivacyFileExists()
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var resourceName = "Ink_Canvas.privacy.txt";
|
||||
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||
{
|
||||
return stream != null;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,361 @@
|
||||
<ui:Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.CanvasPage"
|
||||
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:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
|
||||
xmlns:i18n="clr-namespace:Ink_Canvas.MarkupExtensions"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:controls="clr-namespace:Ink_Canvas.Controls;assembly=InkCanvas.Controls"
|
||||
xmlns:c="clr-namespace:Ink_Canvas.Converter"
|
||||
mc:Ignorable="d"
|
||||
|
||||
Title="画板">
|
||||
|
||||
<ScrollViewer PanningMode="VerticalFirst">
|
||||
<Grid Margin="59,0,59,0">
|
||||
<FrameworkElement.Resources>
|
||||
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
|
||||
<c:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
|
||||
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
|
||||
TargetType="TextBlock">
|
||||
<Style.Setters>
|
||||
<Setter Property="Margin" Value="1,30,0,6" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</FrameworkElement.Resources>
|
||||
<Grid>
|
||||
<ikw:SimpleStackPanel MaxWidth="1000"
|
||||
HorizontalAlignment="Stretch"
|
||||
Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="{i18n:I18n Key=Canvas_GroupTitle}" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardShowCursor"
|
||||
Header="{i18n:I18n Key=Canvas_ShowCursor}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.PointerHand}"
|
||||
SwitchName="ToggleSwitchShowCursor"
|
||||
Toggled="ToggleSwitchShowCursor_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardEnablePressureTouchMode"
|
||||
Header="{i18n:I18n Key=Canvas_EnablePressureTouch}"
|
||||
Description="{i18n:I18n Key=Canvas_EnablePressureTouchHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Touch}"
|
||||
SwitchName="ToggleSwitchEnablePressureTouchMode"
|
||||
Toggled="ToggleSwitchEnablePressureTouchMode_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardDisablePressure"
|
||||
Header="{i18n:I18n Key=Canvas_DisablePressure}"
|
||||
Description="{i18n:I18n Key=Canvas_DisablePressureHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.TouchPointer}"
|
||||
SwitchName="ToggleSwitchDisablePressure"
|
||||
Toggled="ToggleSwitchDisablePressure_Toggled" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Canvas_EraserSize}"
|
||||
Description="{i18n:I18n Key=Canvas_EraserSizeHint}">
|
||||
<ui:SettingsCard.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.EraseTool}" />
|
||||
</ui:SettingsCard.HeaderIcon>
|
||||
<ComboBox x:Name="ComboBoxEraserSize" Width="160"
|
||||
SelectedIndex="2"
|
||||
SelectionChanged="ComboBoxEraserSize_SelectionChanged">
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_EraserSize_VerySmall}" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_EraserSize_Small}" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_EraserSize_Medium}" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_EraserSize_Large}" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_EraserSize_VeryLarge}" />
|
||||
</ComboBox>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardHideStrokeWhenSelecting"
|
||||
Header="{i18n:I18n Key=Canvas_HideStrokeWhenSelecting}"
|
||||
Description="{i18n:I18n Key=Canvas_HideStrokeWhenSelectingHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Hide}"
|
||||
SwitchName="ToggleSwitchHideStrokeWhenSelecting"
|
||||
Toggled="ToggleSwitchHideStrokeWhenSelecting_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardClearCanvasAndClearTimeMachine"
|
||||
Header="{i18n:I18n Key=Canvas_ClearInkAlsoClearHistory}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Delete}"
|
||||
SwitchName="ToggleSwitchClearCanvasAndClearTimeMachine"
|
||||
Toggled="ToggleSwitchClearCanvasAndClearTimeMachine_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardClearCanvasAlsoClearImages"
|
||||
Header="{i18n:I18n Key=Canvas_ClearCanvasAlsoClearImages}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Photo}"
|
||||
SwitchName="ToggleSwitchClearCanvasAlsoClearImages"
|
||||
Toggled="ToggleSwitchClearCanvasAlsoClearImages_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardCompressPicturesUploaded"
|
||||
Header="{i18n:I18n Key=Canvas_CompressPicturesUploaded}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Clear}"
|
||||
SwitchName="ToggleSwitchCompressPicturesUploaded"
|
||||
Toggled="ToggleSwitchCompressPicturesUploaded_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardLaunchSeewoVideoShowcaseForWhiteboardBooth"
|
||||
Header="{i18n:I18n Key=Canvas_LaunchSeewoVideoShowcaseForWhiteboardBooth}"
|
||||
Description="{i18n:I18n Key=Canvas_LaunchSeewoVideoShowcaseForWhiteboardBoothHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Video}"
|
||||
SwitchName="ToggleSwitchLaunchSeewoVideoShowcaseForWhiteboardBooth"
|
||||
Toggled="ToggleSwitchLaunchSeewoVideoShowcaseForWhiteboardBooth_Toggled" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Canvas_KeepHyperbolaAsymptote}"
|
||||
Description="{i18n:I18n Key=Canvas_HyperbolaAsymptoteHint}">
|
||||
<ui:SettingsCard.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.AreaChart}" />
|
||||
</ui:SettingsCard.HeaderIcon>
|
||||
<ComboBox x:Name="ComboBoxHyperbolaAsymptoteOption" Width="160"
|
||||
SelectedIndex="0"
|
||||
SelectionChanged="ComboBoxHyperbolaAsymptoteOption_SelectionChanged">
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Yes}" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_No}" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_AskEachTime}" />
|
||||
</ComboBox>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardShowCircleCenter"
|
||||
Header="{i18n:I18n Key=Canvas_ShowCircleCenter}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.CircleRing}"
|
||||
SwitchName="ToggleSwitchShowCircleCenter"
|
||||
Toggled="ToggleSwitchShowCircleCenter_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardFitToCurve"
|
||||
Header="{i18n:I18n Key=Canvas_WPFBezierSmoothing}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.InkingTool}"
|
||||
SwitchName="ToggleSwitchFitToCurve"
|
||||
Toggled="ToggleSwitchFitToCurve_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardAdvancedBezierSmoothing"
|
||||
Header="{i18n:I18n Key=Canvas_AdvancedBezierSmoothing}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.InkingTool}"
|
||||
SwitchName="ToggleSwitchAdvancedBezierSmoothing"
|
||||
Toggled="ToggleSwitchAdvancedBezierSmoothing_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardEnableInkFade"
|
||||
Header="{i18n:I18n Key=Canvas_EnableInkFade}"
|
||||
Description="{i18n:I18n Key=Canvas_EnableInkFadeHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Color}"
|
||||
SwitchName="ToggleSwitchEnableInkFade"
|
||||
Toggled="ToggleSwitchEnableInkFade_Toggled" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Canvas_InkFadeTime}"
|
||||
Visibility="{Binding IsOn, ElementName=CardEnableInkFade, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<ui:SettingsCard.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Stopwatch}" />
|
||||
</ui:SettingsCard.HeaderIcon>
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="12">
|
||||
<Slider x:Name="InkFadeTimeSlider" Width="150" Minimum="1000" Maximum="10000"
|
||||
Value="3000" TickFrequency="1000" IsSnapToTickEnabled="True"
|
||||
ValueChanged="InkFadeTimeSlider_ValueChanged" />
|
||||
<TextBlock Text="{Binding Value, ElementName=InkFadeTimeSlider, StringFormat={}{0:0}ms}"
|
||||
VerticalAlignment="Center" FontSize="14" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardHideInkFadeControlInPenMenu"
|
||||
Header="{i18n:I18n Key=Canvas_HideInkFadeInPenMenu}"
|
||||
Description="{i18n:I18n Key=Canvas_HideInkFadeInPenMenuHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Hide}"
|
||||
SwitchName="ToggleSwitchHideInkFadeControlInPenMenu"
|
||||
Toggled="ToggleSwitchHideInkFadeControlInPenMenu_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardBrushAutoRestore"
|
||||
Header="{i18n:I18n Key=Canvas_BrushAutoRestore}"
|
||||
Description="{i18n:I18n Key=Canvas_BrushAutoRestoreHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Refresh}"
|
||||
SwitchName="ToggleSwitchBrushAutoRestore"
|
||||
Toggled="ToggleSwitchBrushAutoRestore_Toggled" />
|
||||
|
||||
<ui:SettingsExpander Header="{i18n:I18n Key=Canvas_BrushAutoRestore}"
|
||||
Visibility="{Binding IsOn, ElementName=CardBrushAutoRestore, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<ui:SettingsExpander.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
|
||||
</ui:SettingsExpander.HeaderIcon>
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Canvas_AutoRestoreTimePoints}">
|
||||
<TextBox x:Name="BrushAutoRestoreTimesTextBox" Width="260"
|
||||
TextChanged="BrushAutoRestoreTimesTextBox_TextChanged" />
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Canvas_RestoreColor}">
|
||||
<ComboBox x:Name="ComboBoxBrushAutoRestoreColor" Width="200"
|
||||
SelectionChanged="ComboBoxBrushAutoRestoreColor_SelectionChanged">
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Color_Default}" Tag="#FFFF0000" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Color_Black}" Tag="#FF000000" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Color_White}" Tag="#FFFFFFFF" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Color_Red}" Tag="#FFFF0000" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Color_Yellow}" Tag="#FFFFFF00" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Color_Blue}" Tag="#FF2563EB" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Color_Green}" Tag="#FF16A34A" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Color_Orange}" Tag="#FFFB9650" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Canvas_Color_Purple}" Tag="#FF9333EA" />
|
||||
</ComboBox>
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Canvas_RestoreWidth}">
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="12">
|
||||
<Slider x:Name="BrushAutoRestoreWidthSlider" Width="200" Minimum="1" Maximum="20"
|
||||
TickFrequency="1" IsSnapToTickEnabled="True" Value="5"
|
||||
ValueChanged="BrushAutoRestoreWidthSlider_ValueChanged" />
|
||||
<TextBlock Text="{Binding Value, ElementName=BrushAutoRestoreWidthSlider, StringFormat={}{0:0}px}"
|
||||
FontSize="12" VerticalAlignment="Center" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Canvas_RestoreOpacity}">
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="12">
|
||||
<Slider x:Name="BrushAutoRestoreAlphaSlider" Width="200" Minimum="0" Maximum="255"
|
||||
TickFrequency="5" IsSnapToTickEnabled="True"
|
||||
ValueChanged="BrushAutoRestoreAlphaSlider_ValueChanged" />
|
||||
<TextBlock Text="{Binding Value, ElementName=BrushAutoRestoreAlphaSlider, StringFormat={}{0:0}}"
|
||||
FontSize="12" VerticalAlignment="Center" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</ui:SettingsCard>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardEnableEraserAutoSwitchBack"
|
||||
Header="{i18n:I18n Key=Canvas_SwitchBackAfterEraser}"
|
||||
Description="{i18n:I18n Key=Canvas_SwitchBackAfterEraserHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Switch}"
|
||||
SwitchName="ToggleSwitchEnableEraserAutoSwitchBack"
|
||||
Toggled="ToggleSwitchEnableEraserAutoSwitchBack_Toggled" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Canvas_SwitchBackDelay}"
|
||||
Description="{i18n:I18n Key=Canvas_SwitchBackDelayHint}"
|
||||
Visibility="{Binding IsOn, ElementName=CardEnableEraserAutoSwitchBack, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="12">
|
||||
<Slider x:Name="EraserAutoSwitchBackDelaySlider" Width="150" Minimum="1" Maximum="60"
|
||||
Value="10" TickFrequency="1" IsSnapToTickEnabled="True"
|
||||
ValueChanged="EraserAutoSwitchBackDelaySlider_ValueChanged" />
|
||||
<TextBlock Text="{Binding Value, ElementName=EraserAutoSwitchBackDelaySlider, StringFormat={}{0:0}秒}"
|
||||
VerticalAlignment="Center" FontSize="14" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="{i18n:I18n Key=InkRecog_Title}" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardEnableInkToShape"
|
||||
Header="{i18n:I18n Key=InkRecog_EnableInkRecognition}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Draw}"
|
||||
SwitchName="ToggleSwitchEnableInkToShape"
|
||||
Toggled="ToggleSwitchEnableInkToShape_Toggled" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_ShapeEngine}"
|
||||
Description="{i18n:I18n Key=InkRecog_ShapeEngineHint}">
|
||||
<ComboBox x:Name="ComboBoxShapeRecognitionEngine" Width="160"
|
||||
SelectionChanged="ComboBoxShapeRecognitionEngine_SelectionChanged">
|
||||
<ComboBoxItem Content="{i18n:I18n Key=InkRecog_ShapeEngineAuto}" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=InkRecog_ShapeEngineIACore}" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=InkRecog_ShapeEngineWinRT}" />
|
||||
</ComboBox>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardEnableWinRtHandwritingStrokeBeautify"
|
||||
Header="{i18n:I18n Key=InkRecog_HandwritingBeautify}"
|
||||
Description="{i18n:I18n Key=InkRecog_HandwritingBeautifyHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.PenWorkspace}"
|
||||
SwitchName="ToggleSwitchEnableWinRtHandwritingStrokeBeautify"
|
||||
Toggled="ToggleSwitchEnableWinRtHandwritingStrokeBeautify_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardEnableInkToShapeNoFakePressureRectangle"
|
||||
Header="{i18n:I18n Key=InkRecog_BlockRectFakePressure}"
|
||||
ShowWhen="{Binding IsOn, ElementName=CardEnableInkToShape}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.RectangularClipping}"
|
||||
SwitchName="ToggleSwitchEnableInkToShapeNoFakePressureRectangle"
|
||||
Toggled="ToggleSwitchEnableInkToShapeNoFakePressureRectangle_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardEnableInkToShapeNoFakePressureTriangle"
|
||||
Header="{i18n:I18n Key=InkRecog_BlockTriFakePressure}"
|
||||
ShowWhen="{Binding IsOn, ElementName=CardEnableInkToShape}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.IncidentTriangle}"
|
||||
SwitchName="ToggleSwitchEnableInkToShapeNoFakePressureTriangle"
|
||||
Toggled="ToggleSwitchEnableInkToShapeNoFakePressureTriangle_Toggled" />
|
||||
|
||||
<ui:SettingsExpander Header="形状修正"
|
||||
Visibility="{Binding IsOn, ElementName=CardEnableInkToShape, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<ui:SettingsExpander.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
|
||||
</ui:SettingsExpander.HeaderIcon>
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_FixTriangle}">
|
||||
<CheckBox x:Name="ToggleCheckboxEnableInkToShapeTriangle" IsChecked="True"
|
||||
Checked="ToggleCheckboxEnableInkToShapeTriangle_CheckedChanged"
|
||||
Unchecked="ToggleCheckboxEnableInkToShapeTriangle_CheckedChanged" />
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_FixRectangle}">
|
||||
<CheckBox x:Name="ToggleCheckboxEnableInkToShapeRectangle" IsChecked="True"
|
||||
Checked="ToggleCheckboxEnableInkToShapeRectangle_CheckedChanged"
|
||||
Unchecked="ToggleCheckboxEnableInkToShapeRectangle_CheckedChanged" />
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_FixEllipse}">
|
||||
<CheckBox x:Name="ToggleCheckboxEnableInkToShapeRounded" IsChecked="True"
|
||||
Checked="ToggleCheckboxEnableInkToShapeRounded_CheckedChanged"
|
||||
Unchecked="ToggleCheckboxEnableInkToShapeRounded_CheckedChanged" />
|
||||
</ui:SettingsCard>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardAutoStraightenLine"
|
||||
Header="{i18n:I18n Key=InkRecog_AutoStraightLine}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.LineDisplay}"
|
||||
SwitchName="ToggleSwitchAutoStraightenLine"
|
||||
Toggled="ToggleSwitchAutoStraightenLine_Toggled" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_LengthThreshold}"
|
||||
Visibility="{Binding IsOn, ElementName=CardAutoStraightenLine, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="12">
|
||||
<Slider x:Name="AutoStraightenLineThresholdSlider" Width="150" Minimum="30" Maximum="300"
|
||||
Value="80" TickFrequency="30" IsSnapToTickEnabled="True"
|
||||
ValueChanged="AutoStraightenLineThresholdSlider_ValueChanged" />
|
||||
<TextBlock Text="{Binding Value, ElementName=AutoStraightenLineThresholdSlider, StringFormat={}{0:0}}"
|
||||
VerticalAlignment="Center" FontSize="14" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_Sensitivity}"
|
||||
Visibility="{Binding IsOn, ElementName=CardAutoStraightenLine, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="12">
|
||||
<Slider x:Name="LineStraightenSensitivitySlider" Width="150" Minimum="0.05" Maximum="2.0"
|
||||
Value="0.20" TickFrequency="0.05" IsSnapToTickEnabled="True"
|
||||
ValueChanged="LineStraightenSensitivitySlider_ValueChanged" />
|
||||
<TextBlock Text="{Binding Value, ElementName=LineStraightenSensitivitySlider, StringFormat={}{0:F2}}"
|
||||
VerticalAlignment="Center" FontSize="14" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardHighPrecisionLineStraighten"
|
||||
Header="{i18n:I18n Key=InkRecog_HighPrecisionStraighten}"
|
||||
Description="{i18n:I18n Key=InkRecog_HighPrecisionHint}"
|
||||
ShowWhen="{Binding IsOn, ElementName=CardAutoStraightenLine}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Bullseye}"
|
||||
SwitchName="ToggleSwitchHighPrecisionLineStraighten"
|
||||
Toggled="ToggleSwitchHighPrecisionLineStraighten_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardLineEndpointSnapping"
|
||||
Header="{i18n:I18n Key=InkRecog_LineEndpointSnapping}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Link}"
|
||||
SwitchName="ToggleSwitchLineEndpointSnapping"
|
||||
Toggled="ToggleSwitchLineEndpointSnapping_Toggled" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_SnappingDistance}"
|
||||
Description="{i18n:I18n Key=InkRecog_LineEndpointSnappingHint}"
|
||||
Visibility="{Binding IsOn, ElementName=CardLineEndpointSnapping, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="12">
|
||||
<Slider x:Name="LineEndpointSnappingThresholdSlider" Width="150" Minimum="5" Maximum="50"
|
||||
Value="15" TickFrequency="5" IsSnapToTickEnabled="True"
|
||||
ValueChanged="LineEndpointSnappingThresholdSlider_ValueChanged" />
|
||||
<TextBlock Text="{Binding Value, ElementName=LineEndpointSnappingThresholdSlider, StringFormat={}{0:0}}"
|
||||
VerticalAlignment="Center" FontSize="14" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<Rectangle Height="48" />
|
||||
|
||||
</ikw:SimpleStackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</ui:Page>
|
||||
@@ -0,0 +1,403 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using Ink_Canvas.Windows.SettingsViews.Helpers;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Ink_Canvas.Windows.SettingsViews.Pages
|
||||
{
|
||||
public partial class CanvasPage : iNKORE.UI.WPF.Modern.Controls.Page
|
||||
{
|
||||
private bool _isLoaded = false;
|
||||
|
||||
public CanvasPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += CanvasPage_Loaded;
|
||||
}
|
||||
|
||||
private void CanvasPage_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LoadSettings();
|
||||
_isLoaded = true;
|
||||
}
|
||||
|
||||
private void LoadSettings()
|
||||
{
|
||||
_isLoaded = false;
|
||||
|
||||
try
|
||||
{
|
||||
var settings = SettingsManager.Settings;
|
||||
if (settings.Canvas != null)
|
||||
{
|
||||
CardShowCursor.IsOn = settings.Canvas.IsShowCursor;
|
||||
CardEnablePressureTouchMode.IsOn = settings.Canvas.EnablePressureTouchMode;
|
||||
CardDisablePressure.IsOn = settings.Canvas.DisablePressure;
|
||||
ComboBoxEraserSize.SelectedIndex = settings.Canvas.EraserSize;
|
||||
CardHideStrokeWhenSelecting.IsOn = settings.Canvas.HideStrokeWhenSelecting;
|
||||
CardClearCanvasAndClearTimeMachine.IsOn = settings.Canvas.ClearCanvasAndClearTimeMachine;
|
||||
CardClearCanvasAlsoClearImages.IsOn = settings.Canvas.ClearCanvasAlsoClearImages;
|
||||
CardCompressPicturesUploaded.IsOn = settings.Canvas.IsCompressPicturesUploaded;
|
||||
CardLaunchSeewoVideoShowcaseForWhiteboardBooth.IsOn = settings.Canvas.LaunchSeewoVideoShowcaseForWhiteboardBooth;
|
||||
ComboBoxHyperbolaAsymptoteOption.SelectedIndex = (int)settings.Canvas.HyperbolaAsymptoteOption;
|
||||
CardShowCircleCenter.IsOn = settings.Canvas.ShowCircleCenter;
|
||||
CardFitToCurve.IsOn = settings.Canvas.FitToCurve;
|
||||
CardAdvancedBezierSmoothing.IsOn = settings.Canvas.UseAdvancedBezierSmoothing;
|
||||
CardEnableInkFade.IsOn = settings.Canvas.EnableInkFade;
|
||||
InkFadeTimeSlider.Value = settings.Canvas.InkFadeTime;
|
||||
CardHideInkFadeControlInPenMenu.IsOn = settings.Canvas.HideInkFadeControlInPenMenu;
|
||||
CardBrushAutoRestore.IsOn = settings.Canvas.EnableBrushAutoRestore;
|
||||
BrushAutoRestoreTimesTextBox.Text = settings.Canvas.BrushAutoRestoreTimes ?? string.Empty;
|
||||
LoadBrushAutoRestoreColor(settings.Canvas.BrushAutoRestoreColor);
|
||||
BrushAutoRestoreWidthSlider.Value = settings.Canvas.BrushAutoRestoreWidth > 0 ? settings.Canvas.BrushAutoRestoreWidth : 5;
|
||||
BrushAutoRestoreAlphaSlider.Value = settings.Canvas.BrushAutoRestoreAlpha;
|
||||
CardEnableEraserAutoSwitchBack.IsOn = settings.Canvas.EnableEraserAutoSwitchBack;
|
||||
EraserAutoSwitchBackDelaySlider.Value = settings.Canvas.EraserAutoSwitchBackDelaySeconds;
|
||||
CardAutoStraightenLine.IsOn = settings.Canvas.AutoStraightenLine;
|
||||
AutoStraightenLineThresholdSlider.Value = settings.Canvas.AutoStraightenLineThreshold;
|
||||
CardHighPrecisionLineStraighten.IsOn = settings.Canvas.HighPrecisionLineStraighten;
|
||||
CardLineEndpointSnapping.IsOn = settings.Canvas.LineEndpointSnapping;
|
||||
}
|
||||
|
||||
if (settings.InkToShape != null)
|
||||
{
|
||||
CardEnableInkToShape.IsOn = settings.InkToShape.IsInkToShapeEnabled;
|
||||
int eng = settings.InkToShape.ShapeRecognitionEngine;
|
||||
if (eng < 0) eng = 0;
|
||||
if (eng > 2) eng = 2;
|
||||
ComboBoxShapeRecognitionEngine.SelectedIndex = eng;
|
||||
CardEnableWinRtHandwritingStrokeBeautify.IsOn = settings.InkToShape.EnableWinRtHandwritingStrokeBeautify;
|
||||
CardEnableInkToShapeNoFakePressureRectangle.IsOn = settings.InkToShape.IsInkToShapeNoFakePressureRectangle;
|
||||
CardEnableInkToShapeNoFakePressureTriangle.IsOn = settings.InkToShape.IsInkToShapeNoFakePressureTriangle;
|
||||
ToggleCheckboxEnableInkToShapeTriangle.IsChecked = settings.InkToShape.IsInkToShapeTriangle;
|
||||
ToggleCheckboxEnableInkToShapeRectangle.IsChecked = settings.InkToShape.IsInkToShapeRectangle;
|
||||
ToggleCheckboxEnableInkToShapeRounded.IsChecked = settings.InkToShape.IsInkToShapeRounded;
|
||||
LineStraightenSensitivitySlider.Value = settings.InkToShape.LineStraightenSensitivity;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"加载画板设置时出错: {ex.Message}");
|
||||
}
|
||||
|
||||
_isLoaded = true;
|
||||
}
|
||||
|
||||
private void LoadBrushAutoRestoreColor(string hex)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var item in ComboBoxBrushAutoRestoreColor.Items)
|
||||
{
|
||||
if (item is ComboBoxItem cbi && cbi.Tag != null &&
|
||||
string.Equals(cbi.Tag.ToString(), hex, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ComboBoxBrushAutoRestoreColor.SelectedItem = cbi;
|
||||
return;
|
||||
}
|
||||
}
|
||||
ComboBoxBrushAutoRestoreColor.SelectedIndex = 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"加载画笔恢复颜色时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#region 画板设置事件处理
|
||||
|
||||
private void ToggleSwitchShowCursor_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.IsShowCursor = CardShowCursor.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnablePressureTouchMode_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.EnablePressureTouchMode = CardEnablePressureTouchMode.IsOn;
|
||||
if (SettingsManager.Settings.Canvas.EnablePressureTouchMode && SettingsManager.Settings.Canvas.DisablePressure)
|
||||
{
|
||||
SettingsManager.Settings.Canvas.DisablePressure = false;
|
||||
CardDisablePressure.IsOn = false;
|
||||
}
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchDisablePressure_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.DisablePressure = CardDisablePressure.IsOn;
|
||||
if (SettingsManager.Settings.Canvas.DisablePressure && SettingsManager.Settings.Canvas.EnablePressureTouchMode)
|
||||
{
|
||||
SettingsManager.Settings.Canvas.EnablePressureTouchMode = false;
|
||||
CardEnablePressureTouchMode.IsOn = false;
|
||||
}
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ComboBoxEraserSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.EraserSize = ComboBoxEraserSize.SelectedIndex;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchHideStrokeWhenSelecting_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.HideStrokeWhenSelecting = CardHideStrokeWhenSelecting.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchClearCanvasAndClearTimeMachine_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.ClearCanvasAndClearTimeMachine = CardClearCanvasAndClearTimeMachine.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchClearCanvasAlsoClearImages_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.ClearCanvasAlsoClearImages = CardClearCanvasAlsoClearImages.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchCompressPicturesUploaded_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.IsCompressPicturesUploaded = CardCompressPicturesUploaded.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchLaunchSeewoVideoShowcaseForWhiteboardBooth_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.LaunchSeewoVideoShowcaseForWhiteboardBooth = CardLaunchSeewoVideoShowcaseForWhiteboardBooth.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ComboBoxHyperbolaAsymptoteOption_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.HyperbolaAsymptoteOption = (OptionalOperation)ComboBoxHyperbolaAsymptoteOption.SelectedIndex;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchShowCircleCenter_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.ShowCircleCenter = CardShowCircleCenter.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchFitToCurve_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.FitToCurve = CardFitToCurve.IsOn;
|
||||
if (CardFitToCurve.IsOn)
|
||||
{
|
||||
SettingsManager.Settings.Canvas.UseAdvancedBezierSmoothing = false;
|
||||
CardAdvancedBezierSmoothing.IsOn = false;
|
||||
}
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchAdvancedBezierSmoothing_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.UseAdvancedBezierSmoothing = CardAdvancedBezierSmoothing.IsOn;
|
||||
if (CardAdvancedBezierSmoothing.IsOn)
|
||||
{
|
||||
SettingsManager.Settings.Canvas.FitToCurve = false;
|
||||
CardFitToCurve.IsOn = false;
|
||||
}
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnableInkFade_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.EnableInkFade = CardEnableInkFade.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void InkFadeTimeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.InkFadeTime = (int)e.NewValue;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchHideInkFadeControlInPenMenu_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.HideInkFadeControlInPenMenu = CardHideInkFadeControlInPenMenu.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchBrushAutoRestore_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.EnableBrushAutoRestore = CardBrushAutoRestore.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void BrushAutoRestoreTimesTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.BrushAutoRestoreTimes = BrushAutoRestoreTimesTextBox.Text ?? string.Empty;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ComboBoxBrushAutoRestoreColor_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
if (ComboBoxBrushAutoRestoreColor.SelectedItem is ComboBoxItem item)
|
||||
{
|
||||
string hex = item.Tag as string ?? string.Empty;
|
||||
SettingsManager.Settings.Canvas.BrushAutoRestoreColor = hex;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
}
|
||||
|
||||
private void BrushAutoRestoreWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.BrushAutoRestoreWidth = e.NewValue;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void BrushAutoRestoreAlphaSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.BrushAutoRestoreAlpha = (int)e.NewValue;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnableEraserAutoSwitchBack_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.EnableEraserAutoSwitchBack = CardEnableEraserAutoSwitchBack.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void EraserAutoSwitchBackDelaySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.EraserAutoSwitchBackDelaySeconds = (int)e.NewValue;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 墨迹识别事件处理
|
||||
|
||||
private void ToggleSwitchEnableInkToShape_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.InkToShape.IsInkToShapeEnabled = CardEnableInkToShape.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ComboBoxShapeRecognitionEngine_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded || ComboBoxShapeRecognitionEngine == null) return;
|
||||
int idx = ComboBoxShapeRecognitionEngine.SelectedIndex;
|
||||
if (idx < 0) idx = 0;
|
||||
if (idx > 2) idx = 2;
|
||||
SettingsManager.Settings.InkToShape.ShapeRecognitionEngine = idx;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnableWinRtHandwritingStrokeBeautify_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.InkToShape.EnableWinRtHandwritingStrokeBeautify = CardEnableWinRtHandwritingStrokeBeautify.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnableInkToShapeNoFakePressureRectangle_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.InkToShape.IsInkToShapeNoFakePressureRectangle = CardEnableInkToShapeNoFakePressureRectangle.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnableInkToShapeNoFakePressureTriangle_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.InkToShape.IsInkToShapeNoFakePressureTriangle = CardEnableInkToShapeNoFakePressureTriangle.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleCheckboxEnableInkToShapeTriangle_CheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.InkToShape.IsInkToShapeTriangle = (bool)ToggleCheckboxEnableInkToShapeTriangle.IsChecked;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleCheckboxEnableInkToShapeRectangle_CheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.InkToShape.IsInkToShapeRectangle = (bool)ToggleCheckboxEnableInkToShapeRectangle.IsChecked;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleCheckboxEnableInkToShapeRounded_CheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.InkToShape.IsInkToShapeRounded = (bool)ToggleCheckboxEnableInkToShapeRounded.IsChecked;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchAutoStraightenLine_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.AutoStraightenLine = CardAutoStraightenLine.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void AutoStraightenLineThresholdSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.AutoStraightenLineThreshold = (int)e.NewValue;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void LineStraightenSensitivitySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.InkToShape.LineStraightenSensitivity = e.NewValue;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchHighPrecisionLineStraighten_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.HighPrecisionLineStraighten = CardHighPrecisionLineStraighten.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchLineEndpointSnapping_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.LineEndpointSnapping = CardLineEndpointSnapping.IsOn;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void LineEndpointSnappingThresholdSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
SettingsManager.Settings.Canvas.LineEndpointSnappingThreshold = (int)e.NewValue;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,8 @@
|
||||
xmlns:i18n="clr-namespace:Ink_Canvas.MarkupExtensions"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:controls="clr-namespace:Ink_Canvas.Controls;assembly=InkCanvas.Controls"
|
||||
mc:Ignorable="d"
|
||||
xmlns:c="clr-namespace:Ink_Canvas.Converter"
|
||||
mc:Ignorable="d"
|
||||
|
||||
Title="启动">
|
||||
|
||||
@@ -18,6 +19,7 @@
|
||||
<Grid Margin="59,0,59,0">
|
||||
<FrameworkElement.Resources>
|
||||
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
|
||||
<c:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
|
||||
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
|
||||
TargetType="TextBlock">
|
||||
@@ -113,22 +115,17 @@
|
||||
Icon="{x:Static ui:SegoeFluentIcons.ChevronLeft}"
|
||||
SwitchName="ToggleSwitchFoldAtStartup"
|
||||
Toggled="ToggleSwitchFoldAtStartup_Toggled" />
|
||||
|
||||
<!-- 模式设置 -->
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="模式设置" />
|
||||
|
||||
<ui:SettingsExpander Description="{i18n:I18n Key=Settings_ModeDesc}"
|
||||
Header="{i18n:I18n Key=Settings_ModeDesc_1}">
|
||||
<ui:SettingsExpander.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
|
||||
</ui:SettingsExpander.HeaderIcon>
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsCard Header="仅PPT模式">
|
||||
<ui:ToggleSwitch Name="ToggleSwitchPPTOnlyMode" OnContent="{i18n:I18n Key=Common_On}" OffContent="{i18n:I18n Key=Common_Off}" Toggled="ToggleSwitchPPTOnlyMode_Toggled" />
|
||||
</ui:SettingsCard>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
<!-- 运行模式 -->
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="{i18n:I18n Key=Settings_ModeDesc_1}" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardPPTOnlyMode"
|
||||
Header="{i18n:I18n Key=Mode_PPTOnly}"
|
||||
Description="{i18n:I18n Key=Settings_ModeDesc}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Settings}"
|
||||
SwitchName="ToggleSwitchPPTOnlyMode"
|
||||
Toggled="ToggleSwitchPPTOnlyMode_Toggled" />
|
||||
|
||||
<!-- 底部空白 -->
|
||||
<Rectangle Height="48" />
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Ink_Canvas.Windows.SettingsViews.Pages
|
||||
|
||||
if (settings.ModeSettings != null)
|
||||
{
|
||||
ToggleSwitchPPTOnlyMode.IsOn = settings.ModeSettings.IsPPTOnlyMode;
|
||||
CardPPTOnlyMode.IsOn = settings.ModeSettings.IsPPTOnlyMode;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -361,7 +361,7 @@ namespace Ink_Canvas.Windows.SettingsViews.Pages
|
||||
|
||||
try
|
||||
{
|
||||
bool newState = ToggleSwitchPPTOnlyMode.IsOn;
|
||||
bool newState = CardPPTOnlyMode.IsOn;
|
||||
|
||||
var window = Application.Current.MainWindow;
|
||||
if (window != null)
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
<ui:Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.UpdatePage"
|
||||
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:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
|
||||
xmlns:i18n="clr-namespace:Ink_Canvas.MarkupExtensions"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:controls="clr-namespace:Ink_Canvas.Controls;assembly=InkCanvas.Controls"
|
||||
xmlns:c="clr-namespace:Ink_Canvas.Converter"
|
||||
mc:Ignorable="d"
|
||||
|
||||
Title="更新">
|
||||
|
||||
<ScrollViewer PanningMode="VerticalFirst">
|
||||
<Grid Margin="59,0,59,0">
|
||||
<FrameworkElement.Resources>
|
||||
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
|
||||
<c:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
|
||||
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
|
||||
TargetType="TextBlock">
|
||||
<Style.Setters>
|
||||
<Setter Property="Margin" Value="1,30,0,6" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</FrameworkElement.Resources>
|
||||
<Grid>
|
||||
<ikw:SimpleStackPanel MaxWidth="1000"
|
||||
HorizontalAlignment="Stretch"
|
||||
Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="自动更新" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardAutoUpdate"
|
||||
Header="{i18n:I18n Key=Header_AutoUpdate}"
|
||||
Description="{i18n:I18n Key=Startup_AutoUpdateHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Sync}"
|
||||
SwitchName="ToggleSwitchIsAutoUpdate"
|
||||
Toggled="ToggleSwitchIsAutoUpdate_Toggled" />
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardSilentUpdate"
|
||||
Header="{i18n:I18n Key=Header_SilentUpdate}"
|
||||
Description="{i18n:I18n Key=Startup_SilentUpdateHint}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.QuietHours}"
|
||||
SwitchName="ToggleSwitchIsAutoUpdateWithSilence"
|
||||
ShowWhen="{Binding IsOn, ElementName=CardAutoUpdate}"
|
||||
Toggled="ToggleSwitchIsAutoUpdateWithSilence_Toggled" />
|
||||
|
||||
<ui:SettingsExpander x:Name="ExpanderSilentUpdateTime"
|
||||
Header="{i18n:I18n Key=Startup_SilentUpdateTimePeriod}"
|
||||
Visibility="{Binding IsOn, ElementName=CardSilentUpdate, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<ui:SettingsExpander.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
|
||||
</ui:SettingsExpander.HeaderIcon>
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Startup_SilentUpdateFullHint}">
|
||||
<ui:SettingsCard.Content>
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="12">
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal">
|
||||
<TextBlock Margin="0,0,10,0" VerticalAlignment="Center"
|
||||
Text="{i18n:I18n Key=Startup_StartTime}" FontSize="14" />
|
||||
<ComboBox x:Name="AutoUpdateWithSilenceStartTimeComboBox" Width="90"
|
||||
SelectionChanged="AutoUpdateWithSilenceStartTimeComboBox_SelectionChanged" />
|
||||
</ikw:SimpleStackPanel>
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal">
|
||||
<TextBlock Margin="0,0,10,0" VerticalAlignment="Center"
|
||||
Text="{i18n:I18n Key=Startup_EndTime}" FontSize="14" />
|
||||
<ComboBox x:Name="AutoUpdateWithSilenceEndTimeComboBox" Width="90"
|
||||
SelectionChanged="AutoUpdateWithSilenceEndTimeComboBox_SelectionChanged" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</ikw:SimpleStackPanel>
|
||||
</ui:SettingsCard.Content>
|
||||
</ui:SettingsCard>
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Startup_TimePeriodHint}" />
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="更新通道" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Startup_UpdateChannel}"
|
||||
Description="{i18n:I18n Key=Startup_UpdateChannelHint}">
|
||||
<ui:SettingsCard.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.SyncFolder}" />
|
||||
</ui:SettingsCard.HeaderIcon>
|
||||
<ComboBox x:Name="UpdateChannelSelector" Width="160"
|
||||
SelectionChanged="UpdateChannelSelector_SelectionChanged">
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Update_Release}" Tag="Release" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Update_Preview}" Tag="Preview" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Update_Beta}" Tag="Beta" />
|
||||
</ComboBox>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Startup_UpdatePackageArchitecture}"
|
||||
Description="{i18n:I18n Key=Startup_UpdatePackageArchitectureHint}">
|
||||
<ui:SettingsCard.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.DeveloperTools}" />
|
||||
</ui:SettingsCard.HeaderIcon>
|
||||
<ComboBox x:Name="UpdatePackageArchitectureSelector" Width="160"
|
||||
SelectionChanged="UpdatePackageArchitectureSelector_SelectionChanged">
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Update_PackageArch_X86}" Tag="X86" />
|
||||
<ComboBoxItem Content="{i18n:I18n Key=Update_PackageArch_X64}" Tag="X64" />
|
||||
</ComboBox>
|
||||
</ui:SettingsCard>
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="手动操作" />
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Btn_ManualUpdate}"
|
||||
Description="{i18n:I18n Key=Startup_ManualUpdateHint}">
|
||||
<ui:SettingsCard.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Search}" />
|
||||
</ui:SettingsCard.HeaderIcon>
|
||||
<Button x:Name="ManualUpdateButton" Content="{i18n:I18n Key=Btn_ManualUpdate}"
|
||||
Click="ManualUpdateButton_Click" />
|
||||
</ui:SettingsCard>
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Btn_FixVersion}"
|
||||
Description="{i18n:I18n Key=Startup_FixVersionHint}">
|
||||
<ui:SettingsCard.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Repair}" />
|
||||
</ui:SettingsCard.HeaderIcon>
|
||||
<Button x:Name="FixVersionButton" Content="{i18n:I18n Key=Btn_FixVersion}"
|
||||
Click="FixVersionButton_Click" />
|
||||
</ui:SettingsCard>
|
||||
|
||||
<ui:SettingsCard Header="{i18n:I18n Key=Btn_HistoryRollback}"
|
||||
Description="{i18n:I18n Key=Startup_HistoryRollbackHint}">
|
||||
<ui:SettingsCard.HeaderIcon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.History}" />
|
||||
</ui:SettingsCard.HeaderIcon>
|
||||
<Button Content="{i18n:I18n Key=Btn_HistoryRollback}"
|
||||
Click="HistoryRollbackButton_Click" />
|
||||
</ui:SettingsCard>
|
||||
|
||||
<Rectangle Height="48" />
|
||||
|
||||
</ikw:SimpleStackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</ui:Page>
|
||||
@@ -0,0 +1,468 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using Ink_Canvas.Windows.SettingsViews.Helpers;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Ink_Canvas.Windows.SettingsViews.Pages
|
||||
{
|
||||
public partial class UpdatePage : iNKORE.UI.WPF.Modern.Controls.Page
|
||||
{
|
||||
private bool _isLoaded = false;
|
||||
private bool _isChangingUpdateChannelInternally = false;
|
||||
private bool _isChangingUpdatePackageArchInternally = false;
|
||||
|
||||
public UpdatePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += UpdatePage_Loaded;
|
||||
}
|
||||
|
||||
private void UpdatePage_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LoadSettings();
|
||||
_isLoaded = true;
|
||||
}
|
||||
|
||||
private void LoadSettings()
|
||||
{
|
||||
_isLoaded = false;
|
||||
|
||||
try
|
||||
{
|
||||
var settings = SettingsManager.Settings;
|
||||
if (settings.Startup != null)
|
||||
{
|
||||
CardAutoUpdate.IsOn = settings.Startup.IsAutoUpdate;
|
||||
CardSilentUpdate.IsOn = settings.Startup.IsAutoUpdateWithSilence;
|
||||
|
||||
AutoUpdateWithSilenceTimeComboBox.InitializeAutoUpdateWithSilenceTimeComboBoxOptions(
|
||||
AutoUpdateWithSilenceStartTimeComboBox, AutoUpdateWithSilenceEndTimeComboBox);
|
||||
AutoUpdateWithSilenceStartTimeComboBox.SelectedItem = settings.Startup.AutoUpdateWithSilenceStartTime;
|
||||
AutoUpdateWithSilenceEndTimeComboBox.SelectedItem = settings.Startup.AutoUpdateWithSilenceEndTime;
|
||||
|
||||
foreach (var item in UpdateChannelSelector.Items)
|
||||
{
|
||||
if (item is ComboBoxItem cbi && cbi.Tag != null &&
|
||||
string.Equals(cbi.Tag.ToString(), settings.Startup.UpdateChannel.ToString(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
UpdateChannelSelector.SelectedItem = cbi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_isChangingUpdatePackageArchInternally = true;
|
||||
try
|
||||
{
|
||||
string wantTag = settings.Startup.UpdatePackageArchitecture == UpdatePackageArchitecture.X64 ? "X64" : "X86";
|
||||
foreach (var item in UpdatePackageArchitectureSelector.Items)
|
||||
{
|
||||
if (item is ComboBoxItem cbi && cbi.Tag != null &&
|
||||
string.Equals(cbi.Tag.ToString(), wantTag, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
UpdatePackageArchitectureSelector.SelectedItem = cbi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isChangingUpdatePackageArchInternally = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"加载更新设置时出错: {ex.Message}");
|
||||
}
|
||||
|
||||
_isLoaded = true;
|
||||
}
|
||||
|
||||
#region 自动更新事件处理
|
||||
|
||||
private void ToggleSwitchIsAutoUpdate_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
|
||||
try
|
||||
{
|
||||
bool newState = CardAutoUpdate.IsOn;
|
||||
SettingsManager.Settings.Startup.IsAutoUpdate = newState;
|
||||
|
||||
if (!newState)
|
||||
{
|
||||
SettingsManager.Settings.Startup.IsAutoUpdateWithSilence = false;
|
||||
CardSilentUpdate.IsOn = false;
|
||||
}
|
||||
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"设置自动更新时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ToggleSwitchIsAutoUpdateWithSilence_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
|
||||
try
|
||||
{
|
||||
bool newState = CardSilentUpdate.IsOn;
|
||||
SettingsManager.Settings.Startup.IsAutoUpdateWithSilence = newState;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"设置静默更新时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void AutoUpdateWithSilenceStartTimeComboBox_SelectionChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
|
||||
try
|
||||
{
|
||||
SettingsManager.Settings.Startup.AutoUpdateWithSilenceStartTime =
|
||||
(string)AutoUpdateWithSilenceStartTimeComboBox.SelectedItem;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"设置静默更新开始时间时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void AutoUpdateWithSilenceEndTimeComboBox_SelectionChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
|
||||
try
|
||||
{
|
||||
SettingsManager.Settings.Startup.AutoUpdateWithSilenceEndTime =
|
||||
(string)AutoUpdateWithSilenceEndTimeComboBox.SelectedItem;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"设置静默更新结束时间时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 更新通道和架构事件处理
|
||||
|
||||
private void UpdatePackageArchitectureSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
if (_isChangingUpdatePackageArchInternally) return;
|
||||
if (!(UpdatePackageArchitectureSelector.SelectedItem is ComboBoxItem cbi) || cbi.Tag == null) return;
|
||||
|
||||
var newArch = string.Equals(cbi.Tag.ToString(), "X64", StringComparison.OrdinalIgnoreCase)
|
||||
? UpdatePackageArchitecture.X64
|
||||
: UpdatePackageArchitecture.X86;
|
||||
|
||||
if (SettingsManager.Settings.Startup.UpdatePackageArchitecture == newArch)
|
||||
return;
|
||||
|
||||
SettingsManager.Settings.Startup.UpdatePackageArchitecture = newArch;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
LogHelper.WriteLogToFile($"Settings | Update package architecture: {newArch}");
|
||||
}
|
||||
|
||||
private async void UpdateChannelSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (!_isLoaded) return;
|
||||
if (_isChangingUpdateChannelInternally) return;
|
||||
if (!(UpdateChannelSelector.SelectedItem is ComboBoxItem cbi) || cbi.Tag == null) return;
|
||||
|
||||
var oldChannel = SettingsManager.Settings.Startup.UpdateChannel;
|
||||
string channel = cbi.Tag.ToString();
|
||||
UpdateChannel newChannel = channel == "Beta" ? UpdateChannel.Beta
|
||||
: channel == "Preview" ? UpdateChannel.Preview
|
||||
: UpdateChannel.Release;
|
||||
|
||||
if (SettingsManager.Settings.Startup.UpdateChannel == newChannel)
|
||||
return;
|
||||
|
||||
bool isTestChannel = newChannel == UpdateChannel.Preview || newChannel == UpdateChannel.Beta;
|
||||
|
||||
if (isTestChannel && !SettingsManager.Settings.Startup.HasAcceptedTelemetryPrivacy)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"加入预览 / 测试通道前,请先在关于页面勾选\u201C我已阅读并同意 privacy 中的隐私说明\u201D。",
|
||||
"需要同意隐私说明",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Warning);
|
||||
|
||||
SettingsManager.Settings.Startup.UpdateChannel = oldChannel;
|
||||
RevertChannelSelection(oldChannel);
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
LogHelper.WriteLogToFile("Settings | User not accepted privacy, reverted update channel");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTestChannel && SettingsManager.Settings.Startup.TelemetryUploadLevel == TelemetryUploadLevel.None)
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
"加入预览 / 测试通道需要开启匿名基础数据上传。\n\n是否立即开启匿名基础数据上传?",
|
||||
"需要开启匿名使用数据上传",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Warning);
|
||||
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
SettingsManager.Settings.Startup.TelemetryUploadLevel = TelemetryUploadLevel.Basic;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
LogHelper.WriteLogToFile("Settings | Telemetry enabled (Basic) for preview/beta update channel");
|
||||
}
|
||||
else
|
||||
{
|
||||
SettingsManager.Settings.Startup.UpdateChannel = oldChannel;
|
||||
RevertChannelSelection(oldChannel);
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
LogHelper.WriteLogToFile("Settings | User declined telemetry, reverted update channel");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SettingsManager.Settings.Startup.UpdateChannel = newChannel;
|
||||
DeviceIdentifier.UpdateUsageChannel(newChannel);
|
||||
LogHelper.WriteLogToFile($"Settings | Update channel changed to {SettingsManager.Settings.Startup.UpdateChannel}");
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
|
||||
if (SettingsManager.Settings.Startup.IsAutoUpdate)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Channel changed to {newChannel}, performing immediate update check");
|
||||
|
||||
var mainWindow = Application.Current.MainWindow as MainWindow;
|
||||
if (mainWindow != null)
|
||||
{
|
||||
mainWindow.ResetUpdateCheckRetry();
|
||||
await System.Threading.Tasks.Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
mainWindow.AutoUpdate();
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error during channel switch update check: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Channel changed to {newChannel}, but auto-update is disabled");
|
||||
}
|
||||
}
|
||||
|
||||
private void RevertChannelSelection(UpdateChannel targetChannel)
|
||||
{
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
_isChangingUpdateChannelInternally = true;
|
||||
try
|
||||
{
|
||||
string targetTag = targetChannel.ToString();
|
||||
foreach (var item in UpdateChannelSelector.Items)
|
||||
{
|
||||
if (item is ComboBoxItem cbi && cbi.Tag != null &&
|
||||
string.Equals(cbi.Tag.ToString(), targetTag, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
UpdateChannelSelector.SelectedItem = cbi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isChangingUpdateChannelInternally = false;
|
||||
}
|
||||
}), DispatcherPriority.Normal);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 手动操作事件处理
|
||||
|
||||
private async void ManualUpdateButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ManualUpdateButton.IsEnabled = false;
|
||||
ManualUpdateButton.Content = "正在检查更新...";
|
||||
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | Manual update button clicked");
|
||||
|
||||
var (remoteVersion, lineGroup, apiReleaseNotes) = await AutoUpdateHelper.CheckForUpdates(SettingsManager.Settings.Startup.UpdateChannel, true, false);
|
||||
|
||||
if (remoteVersion != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"ManualUpdate | Found new version: {remoteVersion}");
|
||||
|
||||
string currentVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
|
||||
HasNewUpdateWindow updateWindow = new HasNewUpdateWindow(currentVersion, remoteVersion, "", apiReleaseNotes);
|
||||
updateWindow.Owner = Application.Current.MainWindow;
|
||||
bool? dialogResult = updateWindow.ShowDialog();
|
||||
|
||||
if (dialogResult != true)
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | Update dialog closed without selection");
|
||||
return;
|
||||
}
|
||||
|
||||
var mainWindow = Application.Current.MainWindow as MainWindow;
|
||||
|
||||
switch (updateWindow.Result)
|
||||
{
|
||||
case HasNewUpdateWindow.UpdateResult.UpdateNow:
|
||||
LogHelper.WriteLogToFile("ManualUpdate | User chose to update now");
|
||||
MessageBox.Show("开始下载更新,请稍候...", "正在更新", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
|
||||
bool isDownloadSuccessful = mainWindow != null
|
||||
&& await mainWindow.DownloadUpdateWithFallback(remoteVersion, lineGroup, SettingsManager.Settings.Startup.UpdateChannel);
|
||||
|
||||
if (isDownloadSuccessful)
|
||||
{
|
||||
MessageBoxResult result = MessageBox.Show("更新已下载完成,点击确定后将关闭软件并安装新版本!", "安装更新", MessageBoxButton.OKCancel, MessageBoxImage.Information);
|
||||
|
||||
if (result == MessageBoxResult.OK)
|
||||
{
|
||||
App.IsAppExitByUser = true;
|
||||
AutoUpdateHelper.InstallNewVersionApp(remoteVersion, true);
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | User cancelled update installation");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("更新下载失败,请检查网络连接后重试。", "下载失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
break;
|
||||
|
||||
case HasNewUpdateWindow.UpdateResult.UpdateLater:
|
||||
LogHelper.WriteLogToFile("ManualUpdate | User chose to update later");
|
||||
|
||||
isDownloadSuccessful = mainWindow != null
|
||||
&& await mainWindow.DownloadUpdateWithFallback(remoteVersion, lineGroup, SettingsManager.Settings.Startup.UpdateChannel);
|
||||
|
||||
if (isDownloadSuccessful)
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | Update downloaded successfully, will install when application closes");
|
||||
SettingsManager.Settings.Startup.IsAutoUpdate = true;
|
||||
SettingsManager.Settings.Startup.IsAutoUpdateWithSilence = true;
|
||||
|
||||
if (mainWindow != null)
|
||||
mainWindow.StartSilentUpdateTimer();
|
||||
|
||||
MessageBox.Show("更新已下载完成,将在软件关闭时自动安装。", "更新已准备就绪", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | Update download failed", LogHelper.LogType.Error);
|
||||
MessageBox.Show("更新下载失败,请检查网络连接后重试。", "下载失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
break;
|
||||
|
||||
case HasNewUpdateWindow.UpdateResult.SkipVersion:
|
||||
LogHelper.WriteLogToFile($"ManualUpdate | User chose to skip version {remoteVersion}");
|
||||
SettingsManager.Settings.Startup.SkippedVersion = remoteVersion;
|
||||
SettingsManager.SaveSettingsToFile();
|
||||
MessageBox.Show($"已设置跳过版本 {remoteVersion},在下次发布新版本之前不会再提示更新。",
|
||||
"已跳过此版本",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | No updates available");
|
||||
MessageBox.Show("当前已是最新版本!", "无可用更新", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"Error in ManualUpdateButton_Click: {ex.Message}", LogHelper.LogType.Error);
|
||||
MessageBox.Show(
|
||||
$"手动更新过程中发生错误: {ex.Message}",
|
||||
"更新错误",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ManualUpdateButton.IsEnabled = true;
|
||||
ManualUpdateButton.Content = "手动更新";
|
||||
}
|
||||
}
|
||||
|
||||
private async void FixVersionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var confirm = MessageBox.Show(
|
||||
"此操作将下载当前选择通道的最新版本并安装,软件将自动关闭并更新。\n\n确定要执行版本修复吗?",
|
||||
"版本修复确认",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Question);
|
||||
|
||||
if (confirm == MessageBoxResult.Yes)
|
||||
{
|
||||
FixVersionButton.IsEnabled = false;
|
||||
FixVersionButton.Content = "正在修复...";
|
||||
|
||||
try
|
||||
{
|
||||
bool result = await AutoUpdateHelper.FixVersion(SettingsManager.Settings.Startup.UpdateChannel);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"版本修复失败,可能是网络问题或当前已是最新版本。",
|
||||
"修复失败",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error);
|
||||
|
||||
FixVersionButton.IsEnabled = true;
|
||||
FixVersionButton.Content = "版本修复";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"Error in FixVersionButton_Click: {ex.Message}", LogHelper.LogType.Error);
|
||||
MessageBox.Show(
|
||||
$"版本修复过程中发生错误: {ex.Message}",
|
||||
"修复错误",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error);
|
||||
|
||||
FixVersionButton.IsEnabled = true;
|
||||
FixVersionButton.Content = "版本修复";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HistoryRollbackButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var win = new HistoryRollbackWindow(SettingsManager.Settings.Startup.UpdateChannel);
|
||||
win.Owner = Application.Current.MainWindow;
|
||||
win.ShowDialog();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -147,86 +147,39 @@
|
||||
</ui:NavigationViewItem.MenuItems>
|
||||
</ui:NavigationViewItem>
|
||||
|
||||
<!-- 页面2 -->
|
||||
<!-- 更新设置 -->
|
||||
<ui:NavigationViewItem
|
||||
x:Name="Page2Item"
|
||||
Content="页面 2"
|
||||
Tag="Page2Page">
|
||||
x:Name="UpdatePageItem"
|
||||
Content="更新"
|
||||
Tag="UpdatePage"
|
||||
ToolTipService.ToolTip="更新设置">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<ui:SymbolIcon Symbol="Document" />
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Sync}"/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
|
||||
<!-- 设计设置 -->
|
||||
<!-- 画板设置 -->
|
||||
<ui:NavigationViewItem
|
||||
x:Name="DesignItem"
|
||||
Content="设计"
|
||||
Tag="DesignPage"
|
||||
SelectsOnInvoked="True">
|
||||
x:Name="CanvasPageItem"
|
||||
Content="画板"
|
||||
Tag="CanvasPage"
|
||||
ToolTipService.ToolTip="画板与墨迹设置">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Design}"/>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Edit}"/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
<ui:NavigationViewItem.MenuItems>
|
||||
<ui:NavigationViewItem
|
||||
x:Name="IconographyItem"
|
||||
Content="图标"
|
||||
Tag="IconographyPage"
|
||||
ToolTipService.ToolTip="图标设置">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.AllApps}"/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem
|
||||
x:Name="TypographyItem"
|
||||
Content="排版"
|
||||
Tag="TypographyPage"
|
||||
ToolTipService.ToolTip="排版设置">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Font}"/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
</ui:NavigationViewItem.MenuItems>
|
||||
</ui:NavigationViewItem>
|
||||
|
||||
<!-- 外观设置 -->
|
||||
<!-- Debug -->
|
||||
<ui:NavigationViewItem
|
||||
x:Name="AppearanceItem"
|
||||
Content="外观"
|
||||
Tag="AppearancePage"
|
||||
SelectsOnInvoked="True">
|
||||
x:Name="DebugPageItem"
|
||||
Content="Debug"
|
||||
Tag="DebugPage"
|
||||
ToolTipService.ToolTip="Debug">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Color}"/>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.DeveloperTools}"/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
<ui:NavigationViewItem.MenuItems>
|
||||
<ui:NavigationViewItem
|
||||
x:Name="ThemeItem"
|
||||
Content="主题"
|
||||
Tag="ThemePage"
|
||||
ToolTipService.ToolTip="主题设置">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:FluentSystemIcons.DarkTheme_24_Regular}"/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem
|
||||
x:Name="ColorsItem"
|
||||
Content="颜色"
|
||||
Tag="ColorsPage"
|
||||
ToolTipService.ToolTip="颜色设置">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Highlight}"/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem
|
||||
x:Name="FontsItem"
|
||||
Content="字体"
|
||||
Tag="FontsPage"
|
||||
ToolTipService.ToolTip="字体设置">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Font}"/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
</ui:NavigationViewItem.MenuItems>
|
||||
</ui:NavigationViewItem>
|
||||
|
||||
<ui:NavigationViewItemHeader Content="插件设置"/>
|
||||
<ui:NavigationViewItem
|
||||
x:Name="PluginItem"
|
||||
|
||||
@@ -36,15 +36,10 @@ namespace Ink_Canvas.Windows.SettingsViews
|
||||
{
|
||||
{ "HomePage", typeof(HomePage) },
|
||||
{ "BasicPage", typeof(BasicPage) },
|
||||
{ "Page2Page", typeof(Page2Page) },
|
||||
{ "DesignPage", typeof(DesignPage) },
|
||||
{ "AppearancePage", typeof(AppearancePage) },
|
||||
{ "IconographyPage", typeof(IconographyPage) },
|
||||
{ "TypographyPage", typeof(TypographyPage) },
|
||||
{ "ThemePage", typeof(ThemePage) },
|
||||
{ "ColorsPage", typeof(ColorsPage) },
|
||||
{ "FontsPage", typeof(FontsPage) },
|
||||
{ "StartupPage", typeof(StartupPage) },
|
||||
{ "UpdatePage", typeof(UpdatePage) },
|
||||
{ "CanvasPage", typeof(CanvasPage) },
|
||||
{ "DebugPage", typeof(IconographyPage) },
|
||||
{ "AboutPage", typeof(AboutPage) },
|
||||
{ "Settings", typeof(SettingsPage) },
|
||||
{ "PluginPage", typeof(PluginPage) },
|
||||
|
||||
Reference in New Issue
Block a user