Compare commits

...

3 Commits

Author SHA1 Message Date
lincube
9045624105 0.8.0.3
自习功能可关闭
2026-03-31 01:16:53 +08:00
lincube
2dc729c9db 0.8.0.2 2026-03-31 00:03:09 +08:00
lincube
5804627f53 0.8.0.1
修圆角
2026-03-30 20:28:39 +08:00
38 changed files with 281 additions and 76 deletions

View File

@@ -205,6 +205,8 @@
"settings.weather.footer_hint": "Desktop weather widgets will reuse the location and alert exclusion settings configured here.",
"settings.study.title": "Study",
"settings.study.description": "Configure study environment monitoring, focus timer, and alert settings.",
"settings.study.master_switch_header": "Study Feature",
"settings.study.master_switch_desc": "Enable study environment monitoring and focus timer. When disabled, related components will not collect any data.",
"settings.study.noise_header": "Noise Monitoring",
"settings.study.noise_description": "Configure microphone sampling rate and noise scoring sensitivity.",
"settings.study.sampling_rate_label": "Sampling Rate",
@@ -883,6 +885,8 @@
"recording.widget.hint.saved_format": "Saved {0}",
"recording.widget.save_picker_title": "Save recording file",
"recording.widget.save_picker_type": "WAV audio",
"study.widget.disabled_title": "Study Feature Disabled",
"study.widget.disabled_hint": "Please enable in Settings",
"study.environment.status_label": "Environment",
"study.environment.status.initializing": "Initializing",
"study.environment.status.ready": "Ready",

View File

@@ -208,6 +208,8 @@
"settings.weather.location_saved_format": "天气位置已保存:{0}",
"settings.study.title": "自习",
"settings.study.description": "配置自习环境监测、专注计时和提醒设置。",
"settings.study.master_switch_header": "自习功能",
"settings.study.master_switch_desc": "启用自习环境监测和专注计时功能。关闭后,相关组件将不会采集任何数据。",
"settings.study.noise_header": "噪音监测",
"settings.study.noise_description": "配置麦克风采集频率和噪音评分敏感度。",
"settings.study.sampling_rate_label": "采集频率",
@@ -876,6 +878,8 @@
"recording.widget.hint.saved_format": "已保存 {0}",
"recording.widget.save_picker_title": "保存录音文件",
"recording.widget.save_picker_type": "WAV 音频",
"study.widget.disabled_title": "自习功能未启用",
"study.widget.disabled_hint": "请在设置中开启",
"study.environment.status_label": "环境状态",
"study.environment.status.initializing": "初始化中",
"study.environment.status.ready": "待机",

View File

@@ -120,6 +120,8 @@ public sealed class AppSettingsSnapshot
#region Study Settings
public bool StudyEnabled { get; set; } = true;
public int? StudyFrameMs { get; set; }
public double? StudyScoreThresholdDbfs { get; set; }

View File

@@ -2342,6 +2342,27 @@ public sealed partial class StudySettingsPageViewModel : ViewModelBase
_isInitializing = false;
}
#region Properties - Master Switch
[ObservableProperty]
private string _masterSwitchHeader = string.Empty;
[ObservableProperty]
private string _masterSwitchDescription = string.Empty;
[ObservableProperty]
private bool _studyEnabled = true;
partial void OnStudyEnabledChanged(bool value)
{
if (!_isInitializing)
{
SaveMasterSwitch();
}
}
#endregion
#region Properties - Noise Monitoring
[ObservableProperty]
@@ -2686,6 +2707,9 @@ public sealed partial class StudySettingsPageViewModel : ViewModelBase
{
var appSnapshot = _settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App);
// Master switch
StudyEnabled = appSnapshot.StudyEnabled;
// Noise settings
SamplingRateMs = appSnapshot.StudyFrameMs is > 0 ? appSnapshot.StudyFrameMs.Value : 50;
NoiseSensitivityDbfs = appSnapshot.StudyScoreThresholdDbfs ?? -50;
@@ -2718,6 +2742,14 @@ public sealed partial class StudySettingsPageViewModel : ViewModelBase
UpdateAvgWindowSecText();
}
private void SaveMasterSwitch()
{
var appSnapshot = _settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App);
appSnapshot.StudyEnabled = StudyEnabled;
_settingsFacade.Settings.SaveSnapshot(SettingsScope.App, appSnapshot,
changedKeys: [nameof(AppSettingsSnapshot.StudyEnabled)]);
}
private void SaveNoiseSettings()
{
var appSnapshot = _settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App);
@@ -2796,6 +2828,9 @@ public sealed partial class StudySettingsPageViewModel : ViewModelBase
private void RefreshLocalizedText()
{
MasterSwitchHeader = L("settings.study.master_switch_header", "自习功能");
MasterSwitchDescription = L("settings.study.master_switch_desc", "启用自习环境监测和专注计时功能。关闭后,相关组件将不会采集任何数据。");
NoiseMonitoringHeader = L("settings.study.noise_header", "噪音监测");
NoiseMonitoringDescription = L("settings.study.noise_description", "配置麦克风采集频率和噪音评分敏感度。");
SamplingRateLabel = L("settings.study.sampling_rate_label", "采集频率");

View File

@@ -8,7 +8,7 @@
x:Class="LanMountainDesktop.Views.Components.AnalogClockWidget">
<Border x:Name="RootBorder"
CornerRadius="42"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
ClipToBounds="True"
Padding="14">
<Border.Background>

View File

@@ -19,7 +19,7 @@
RowSpacing="8">
<Border x:Name="WebViewHostBorder"
Grid.Row="0"
CornerRadius="16"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
ClipToBounds="True"
Background="#FFFFFFFF"
BorderBrush="#22000000"
@@ -52,7 +52,7 @@
<Border x:Name="AddressBarBorder"
Grid.Row="1"
CornerRadius="14"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#ECF2FA"
BorderBrush="#22000000"
BorderThickness="1"

View File

@@ -94,7 +94,7 @@
Grid.Column="1"
Width="160"
Height="90"
CornerRadius="16"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
ClipToBounds="True"
Background="#E6E6E6">
<Image x:Name="News1Image"
@@ -122,7 +122,7 @@
Grid.Column="1"
Width="160"
Height="90"
CornerRadius="16"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
ClipToBounds="True"
Background="#E6E6E6">
<Image x:Name="News2Image"

View File

@@ -88,7 +88,7 @@
Grid.Row="2"
Width="118"
Height="3"
CornerRadius="2"
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
HorizontalAlignment="Left"
Margin="0,0,0,10"
Background="#F0F0F0" />

View File

@@ -16,7 +16,7 @@
<StackPanel x:Name="RootStackPanel" Spacing="16">
<Border x:Name="CoverImageBorder"
CornerRadius="12"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
ClipToBounds="True"
Background="#f8f5ec"
PointerPressed="OnCoverImagePointerPressed"
@@ -75,7 +75,7 @@
<Border x:Name="OverviewBorder"
Background="#f8f5ec"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Padding="12"
Margin="0,0,0,8">
<StackPanel x:Name="OverviewStackPanel" Spacing="12"/>
@@ -85,7 +85,7 @@
Content="展开更多新闻 ▼"
FontSize="14"
Padding="16,8"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Background="Transparent"
BorderBrush="#bb5649"
BorderThickness="1"

View File

@@ -75,7 +75,7 @@
Height="26"
VerticalAlignment="Center"
Margin="0,0,8,0"
CornerRadius="3"
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
Background="#6BF2A497" />
<TextBlock x:Name="AuthorTextBlock"

View File

@@ -87,7 +87,7 @@
Grid.Column="1"
Background="{DynamicResource AdaptiveLayer2Brush}"
BorderThickness="1"
CornerRadius="24"
CornerRadius="{DynamicResource DesignCornerRadiusLg}"
BoxShadow="0 8 18 #1A000000"
Padding="14">
<Grid x:Name="RightPanelGrid"

View File

@@ -9,7 +9,7 @@
<UserControl.Styles>
<Style Selector="Button">
<Setter Property="CornerRadius" Value="16" />
<Setter Property="CornerRadius" Value="{DynamicResource DesignCornerRadiusSm}" />
<Setter Property="Background" Value="#F8F9FB" />
<Setter Property="BorderBrush" Value="#00000000" />
<Setter Property="BorderThickness" Value="0" />
@@ -40,7 +40,7 @@
<Border x:Name="FromCurrencyRowBorder"
Grid.Row="0"
Grid.Column="0"
CornerRadius="16"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#F8F9FB"
Padding="12,8"
PointerPressed="OnFromCurrencyRowPointerPressed">
@@ -81,7 +81,7 @@
<Border x:Name="ToCurrencyRowBorder"
Grid.Row="1"
Grid.Column="0"
CornerRadius="16"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#F8F9FB"
Padding="12,8"
PointerPressed="OnToCurrencyRowPointerPressed">
@@ -123,7 +123,7 @@
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
CornerRadius="16"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#F8F9FB"
BorderBrush="#00000000"
BorderThickness="0"

View File

@@ -31,12 +31,12 @@
</Border>
<Border x:Name="BackgroundTintLayer"
CornerRadius="28"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
ClipToBounds="True"
Opacity="0.12" />
<Border x:Name="BackgroundLightLayer"
CornerRadius="28"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
ClipToBounds="True"
Opacity="0.54">
<Border.Background>
@@ -53,7 +53,7 @@
</Border>
<Border x:Name="BackgroundShadeLayer"
CornerRadius="28"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
ClipToBounds="True"
Opacity="0.70">
<Border.Background>

View File

@@ -28,9 +28,9 @@
</Border.RenderTransform>
</Border>
<Border x:Name="BackgroundTintLayer" CornerRadius="28" ClipToBounds="True" Opacity="0.12" />
<Border x:Name="BackgroundTintLayer" CornerRadius="{DynamicResource DesignCornerRadiusComponent}" ClipToBounds="True" Opacity="0.12" />
<Border x:Name="BackgroundLightLayer" CornerRadius="28" ClipToBounds="True" Opacity="0.52">
<Border x:Name="BackgroundLightLayer" CornerRadius="{DynamicResource DesignCornerRadiusComponent}" ClipToBounds="True" Opacity="0.52">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#45FFFFFF" Offset="0" />
@@ -40,7 +40,7 @@
</Border.Background>
</Border>
<Border x:Name="BackgroundShadeLayer" CornerRadius="28" ClipToBounds="True" Opacity="0.68">
<Border x:Name="BackgroundShadeLayer" CornerRadius="{DynamicResource DesignCornerRadiusComponent}" ClipToBounds="True" Opacity="0.68">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#00000000" Offset="0.42" />

View File

@@ -40,7 +40,7 @@
VerticalAlignment="Center" />
<Border x:Name="NewsBadge"
Background="#E24B2D"
CornerRadius="4"
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
Padding="6,2"
Margin="4,0,0,0"
VerticalAlignment="Center">

View File

@@ -52,7 +52,7 @@
<Button x:Name="RefreshButton"
Grid.Column="1"
Padding="8,4"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Background="Transparent"
BorderBrush="#bb5649"
BorderThickness="1"

View File

@@ -28,9 +28,9 @@
</Border.RenderTransform>
</Border>
<Border x:Name="BackgroundTintLayer" CornerRadius="28" ClipToBounds="True" Opacity="0.12" />
<Border x:Name="BackgroundTintLayer" CornerRadius="{DynamicResource DesignCornerRadiusComponent}" ClipToBounds="True" Opacity="0.12" />
<Border x:Name="BackgroundLightLayer" CornerRadius="28" ClipToBounds="True" Opacity="0.52">
<Border x:Name="BackgroundLightLayer" CornerRadius="{DynamicResource DesignCornerRadiusComponent}" ClipToBounds="True" Opacity="0.52">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#45FFFFFF" Offset="0" />
@@ -40,7 +40,7 @@
</Border.Background>
</Border>
<Border x:Name="BackgroundShadeLayer" CornerRadius="28" ClipToBounds="True" Opacity="0.68">
<Border x:Name="BackgroundShadeLayer" CornerRadius="{DynamicResource DesignCornerRadiusComponent}" ClipToBounds="True" Opacity="0.68">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#00000000" Offset="0.42" />

View File

@@ -91,10 +91,10 @@
</Image>
</Border>
<Border x:Name="DynamicGradientOverlay"
CornerRadius="30"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
ClipToBounds="True" />
<Border x:Name="DynamicSoftLightOverlay"
CornerRadius="30"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
ClipToBounds="True" />
</Grid>
@@ -111,7 +111,7 @@
<Border x:Name="CoverBorder"
Width="56"
Height="56"
CornerRadius="12"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
ClipToBounds="True"
BorderThickness="1"
BorderBrush="#77FFFFFF"

View File

@@ -23,7 +23,7 @@
Height="300"
HorizontalAlignment="Center"
VerticalAlignment="Center"
CornerRadius="34"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
BorderBrush="#00000000"
BorderThickness="0"
Background="Transparent">
@@ -65,7 +65,7 @@
Grid.Column="1"
Width="2"
Height="32"
CornerRadius="1"
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
Background="#F14A40"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
@@ -74,7 +74,7 @@
Grid.Column="2"
Margin="4,0,0,0"
Height="2"
CornerRadius="1"
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
Background="#A3A8B3"
Opacity="0.55"
HorizontalAlignment="Stretch"

View File

@@ -69,12 +69,12 @@
</Grid>
<Border x:Name="PostItem1Host"
Grid.Row="1"
Tag="0"
Background="#F7F8FA"
CornerRadius="10"
Padding="8,6"
PointerPressed="OnPostItemPointerPressed">
Grid.Row="1"
Tag="0"
Background="#F7F8FA"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Padding="8,6"
PointerPressed="OnPostItemPointerPressed">
<Grid x:Name="PostItem1Grid"
ColumnDefinitions="Auto,*"
ColumnSpacing="8">

View File

@@ -29,7 +29,7 @@
<Border x:Name="ModeBadgeBorder"
Grid.Column="1"
Padding="8,3"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
BorderThickness="1"
BorderBrush="#88FFFFFF"
Background="#553B82F6"
@@ -47,7 +47,7 @@
Grid.Row="1"
Spacing="6">
<Border x:Name="SustainedRowBorder"
CornerRadius="10"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#2CFFFFFF"
BorderBrush="#33FFFFFF"
BorderThickness="1"
@@ -76,7 +76,7 @@
</Border>
<Border x:Name="TimeRowBorder"
CornerRadius="10"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#2CFFFFFF"
BorderBrush="#33FFFFFF"
BorderThickness="1"
@@ -105,7 +105,7 @@
</Border>
<Border x:Name="SegmentRowBorder"
CornerRadius="10"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#2CFFFFFF"
BorderBrush="#33FFFFFF"
BorderThickness="1"

View File

@@ -53,6 +53,7 @@ public partial class StudyDeductionReasonsWidget : UserControl, IDesktopComponen
private bool _isOnActivePage = true;
private bool _isCompactMode;
private bool _isUltraCompactMode;
private bool _studyEnabled = true;
private string _languageCode = "zh-CN";
private readonly record struct DeductionMetrics(
@@ -98,7 +99,10 @@ public partial class StudyDeductionReasonsWidget : UserControl, IDesktopComponen
{
_isAttached = true;
ReloadLanguageCode();
_ = _studyAnalyticsService.StartOrResumeMonitoring();
if (_studyEnabled)
{
_ = _studyAnalyticsService.StartOrResumeMonitoring();
}
UpdateTimerState();
RefreshVisual();
}
@@ -142,10 +146,20 @@ public partial class StudyDeductionReasonsWidget : UserControl, IDesktopComponen
private void RefreshVisual()
{
var snapshot = _studyAnalyticsService.GetSnapshot();
var panelColor = ResolvePanelBackgroundColor();
ApplyTypographyByBackground(panelColor);
if (!_studyEnabled)
{
ModeTextBlock.Text = L("study.widget.disabled_hint", "请在设置中开启");
ApplyModeBadgeColor(panelColor, Color.Parse("#FF9AA0A6"));
ApplyLocalizedLabels();
ApplyUnavailableMetrics();
return;
}
var snapshot = _studyAnalyticsService.GetSnapshot();
var isSessionRunning = snapshot.Session.State == StudySessionRuntimeState.Running;
var isSessionReport = snapshot.DataMode == StudyDataMode.SessionReport && snapshot.LastSessionReport is not null;
var isSessionView = isSessionRunning || isSessionReport;
@@ -595,6 +609,7 @@ public partial class StudyDeductionReasonsWidget : UserControl, IDesktopComponen
{
var snapshot = _settingsService.Load();
_languageCode = _localizationService.NormalizeLanguageCode(snapshot.LanguageCode);
_studyEnabled = snapshot.StudyEnabled;
}
private void ApplyVariableFontFamily()

View File

@@ -30,6 +30,7 @@ public partial class StudyEnvironmentWidget : UserControl, IDesktopComponentWidg
private bool _isAttached;
private bool _isOnActivePage = true;
private bool _isDisposed;
private bool _studyEnabled = true;
private IDisposable? _monitoringLease;
public StudyEnvironmentWidget()
@@ -132,6 +133,13 @@ public partial class StudyEnvironmentWidget : UserControl, IDesktopComponentWidg
private void UpdateMonitoringLeaseState()
{
if (!_studyEnabled)
{
_monitoringLease?.Dispose();
_monitoringLease = null;
return;
}
if (_isAttached)
{
_monitoringLease ??= _monitoringLeaseCoordinator.AcquireLease();
@@ -147,6 +155,7 @@ public partial class StudyEnvironmentWidget : UserControl, IDesktopComponentWidg
var appSnapshot = _appSettingsService.Load();
var componentSnapshot = _componentSettingsService.Load();
_languageCode = _localizationService.NormalizeLanguageCode(appSnapshot.LanguageCode);
_studyEnabled = appSnapshot.StudyEnabled;
_showDisplayDb = componentSnapshot.StudyEnvironmentShowDisplayDb;
_showDbfs = componentSnapshot.StudyEnvironmentShowDbfs;
_componentColorScheme = componentSnapshot.ColorSchemeSource;
@@ -158,6 +167,17 @@ public partial class StudyEnvironmentWidget : UserControl, IDesktopComponentWidg
private void RefreshVisual()
{
if (!_studyEnabled)
{
StatusTitleTextBlock.Text = L("study.widget.disabled_title", "自习功能未启用");
StatusValueTextBlock.Text = L("study.widget.disabled_hint", "请在设置中开启");
StatusValueTextBlock.Foreground = TryResolveThemeBrush("AdaptiveTextSecondaryBrush", "#FF9AA0A6");
NoiseValueTextBlock.Text = "--";
NoiseSubValueTextBlock.IsVisible = false;
UpdateAdaptiveLayout();
return;
}
var snapshot = _studyAnalyticsService.GetSnapshot();
var isSessionReport = snapshot.DataMode == StudyDataMode.SessionReport && snapshot.LastSessionReport is not null;

View File

@@ -29,7 +29,7 @@
<Border x:Name="ModeBadgeBorder"
Grid.Column="1"
Padding="8,3"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
BorderThickness="1"
BorderBrush="#88FFFFFF"
Background="#553B82F6"
@@ -79,7 +79,7 @@
Spacing="6"
VerticalAlignment="Center">
<Border x:Name="CountCardBorder"
CornerRadius="10"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#2CFFFFFF"
BorderBrush="#33FFFFFF"
BorderThickness="1"
@@ -102,7 +102,7 @@
</Border>
<Border x:Name="DurationCardBorder"
CornerRadius="10"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#2CFFFFFF"
BorderBrush="#33FFFFFF"
BorderThickness="1"

View File

@@ -53,6 +53,7 @@ public partial class StudyInterruptDensityWidget : UserControl, IDesktopComponen
private bool _isOnActivePage = true;
private bool _isCompactMode;
private bool _isUltraCompactMode;
private bool _studyEnabled = true;
private string _languageCode = "zh-CN";
private IDisposable? _monitoringLease;
@@ -151,6 +152,13 @@ public partial class StudyInterruptDensityWidget : UserControl, IDesktopComponen
private void UpdateMonitoringLeaseState()
{
if (!_studyEnabled)
{
_monitoringLease?.Dispose();
_monitoringLease = null;
return;
}
var shouldMonitor = _isAttached && _isOnActivePage;
if (shouldMonitor)
{
@@ -164,11 +172,21 @@ public partial class StudyInterruptDensityWidget : UserControl, IDesktopComponen
private void RefreshVisual()
{
var snapshot = _studyAnalyticsService.GetSnapshot();
var panelColor = ResolvePanelBackgroundColor();
ApplyTypographyByBackground(panelColor);
ApplyLocalizedLabels();
if (!_studyEnabled)
{
ModeTextBlock.Text = L("study.widget.disabled_hint", "请在设置中开启");
ApplyModeBadgeColor(panelColor, Color.Parse("#FF9AA0A6"));
DensityValueTextBlock.Text = "--";
DensityUnitTextBlock.Text = "";
return;
}
var snapshot = _studyAnalyticsService.GetSnapshot();
var isSessionRunning = snapshot.Session.State == StudySessionRuntimeState.Running;
var isSessionReport = snapshot.DataMode == StudyDataMode.SessionReport && snapshot.LastSessionReport is not null;
var isSessionView = isSessionRunning || isSessionReport;
@@ -528,6 +546,7 @@ public partial class StudyInterruptDensityWidget : UserControl, IDesktopComponen
{
var snapshot = _settingsService.Load();
_languageCode = _localizationService.NormalizeLanguageCode(snapshot.LanguageCode);
_studyEnabled = snapshot.StudyEnabled;
}
private void ApplyVariableFontFamily()

View File

@@ -20,7 +20,7 @@
ColumnSpacing="8">
<Border x:Name="StatusBadgeBorder"
Padding="8,3"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Background="#7A0E2235"
BorderBrush="#88FFFFFF"
BorderThickness="1"

View File

@@ -70,6 +70,7 @@ public partial class StudyNoiseCurveWidget : UserControl, IDesktopComponentWidge
private bool _isOnActivePage = true;
private bool _isSubscribed;
private bool _isDisposed;
private bool _studyEnabled = true;
private int _framesSinceCompaction;
private IDisposable? _monitoringLease;
@@ -263,6 +264,13 @@ public partial class StudyNoiseCurveWidget : UserControl, IDesktopComponentWidge
private void UpdateMonitoringLeaseState()
{
if (!_studyEnabled)
{
_monitoringLease?.Dispose();
_monitoringLease = null;
return;
}
if (_isAttached)
{
_monitoringLease ??= _monitoringLeaseCoordinator.AcquireLease();
@@ -278,6 +286,15 @@ public partial class StudyNoiseCurveWidget : UserControl, IDesktopComponentWidge
var panelColor = ResolvePanelBackgroundColor();
ApplyTypographyByBackground(panelColor);
if (!_studyEnabled)
{
StatusTextBlock.Text = L("study.widget.disabled_title", "自习功能未启用");
RealtimeValueTextBlock.Text = L("study.widget.disabled_hint", "请在设置中开启");
ApplyStatusBadgeStyle(StatusVisualKind.Default, panelColor);
ChartControl.UpdateSeries([]);
return;
}
var isSessionReport = snapshot.DataMode == StudyDataMode.SessionReport && snapshot.LastSessionReport is not null;
if (isSessionReport && snapshot.LastSessionReport is not null)
{
@@ -578,6 +595,7 @@ public partial class StudyNoiseCurveWidget : UserControl, IDesktopComponentWidge
{
var snapshot = _settingsService.Load();
_languageCode = _localizationService.NormalizeLanguageCode(snapshot.LanguageCode);
_studyEnabled = snapshot.StudyEnabled;
}
private string L(string key, string fallback)

View File

@@ -39,7 +39,7 @@
<Border x:Name="ModeBadgeBorder"
Grid.Column="2"
Padding="8,3"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
BorderThickness="1"
BorderBrush="#88FFFFFF"
Background="#553B82F6"

View File

@@ -56,6 +56,7 @@ public partial class StudyNoiseDistributionWidget : UserControl, IDesktopCompone
private bool _isDisposed;
private bool _isCompactMode;
private bool _isUltraCompactMode;
private bool _studyEnabled = true;
private IDisposable? _monitoringLease;
private readonly record struct DistributionStats(
@@ -157,6 +158,13 @@ public partial class StudyNoiseDistributionWidget : UserControl, IDesktopCompone
private void UpdateMonitoringLeaseState()
{
if (!_studyEnabled)
{
_monitoringLease?.Dispose();
_monitoringLease = null;
return;
}
if (_isAttached)
{
_monitoringLease ??= _monitoringLeaseCoordinator.AcquireLease();
@@ -169,13 +177,23 @@ public partial class StudyNoiseDistributionWidget : UserControl, IDesktopCompone
private void RefreshVisual()
{
var snapshot = _studyAnalyticsService.GetSnapshot();
var panelColor = ResolvePanelBackgroundColor();
ApplyTypographyByBackground(panelColor);
TitleTextBlock.Text = L("study.noise_distribution.title", "Noise Level Distribution");
ApplyLocalizedAxisLabels();
if (!_studyEnabled)
{
ModeTextBlock.Text = L("study.widget.disabled_hint", "请在设置中开启");
ApplyModeBadgeColor(panelColor, Color.Parse("#FF9AA0A6"));
ChartControl.UpdateSeries([], 45);
SummaryTextBlock.Text = "--";
return;
}
var snapshot = _studyAnalyticsService.GetSnapshot();
var isSessionRunning = snapshot.Session.State == StudySessionRuntimeState.Running;
var isSessionReport = snapshot.DataMode == StudyDataMode.SessionReport && snapshot.LastSessionReport is not null;
var isSessionView = isSessionRunning || isSessionReport;
@@ -570,6 +588,7 @@ public partial class StudyNoiseDistributionWidget : UserControl, IDesktopCompone
{
var snapshot = _settingsService.Load();
_languageCode = _localizationService.NormalizeLanguageCode(snapshot.LanguageCode);
_studyEnabled = snapshot.StudyEnabled;
}
private void ApplyVariableFontFamily()

View File

@@ -31,7 +31,7 @@
<Border x:Name="ModeBadgeBorder"
Grid.Column="1"
Padding="8,3"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
BorderThickness="1"
BorderBrush="#88FFFFFF"
Background="#553B82F6"
@@ -71,7 +71,7 @@
ColumnDefinitions="*,*,*"
ColumnSpacing="10">
<Border x:Name="AverageCardBorder"
CornerRadius="12"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Background="#24FFFFFF"
BorderBrush="#2EFFFFFF"
BorderThickness="1"
@@ -96,7 +96,7 @@
<Border x:Name="MinimumCardBorder"
Grid.Column="1"
CornerRadius="12"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Background="#24FFFFFF"
BorderBrush="#2EFFFFFF"
BorderThickness="1"
@@ -121,7 +121,7 @@
<Border x:Name="MaximumCardBorder"
Grid.Column="2"
CornerRadius="12"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Background="#24FFFFFF"
BorderBrush="#2EFFFFFF"
BorderThickness="1"

View File

@@ -57,6 +57,7 @@ public partial class StudyScoreOverviewWidget : UserControl, IDesktopComponentWi
private bool _isCompactMode;
private bool _isUltraCompactMode;
private bool _isExpandedMode;
private bool _studyEnabled = true;
private string _languageCode = "zh-CN";
private IDisposable? _monitoringLease;
@@ -140,6 +141,13 @@ public partial class StudyScoreOverviewWidget : UserControl, IDesktopComponentWi
private void UpdateMonitoringLeaseState()
{
if (!_studyEnabled)
{
_monitoringLease?.Dispose();
_monitoringLease = null;
return;
}
var shouldMonitor = _isAttached && _isOnActivePage;
if (shouldMonitor)
{
@@ -153,12 +161,22 @@ public partial class StudyScoreOverviewWidget : UserControl, IDesktopComponentWi
private void RefreshVisual()
{
var snapshot = _studyAnalyticsService.GetSnapshot();
ApplyLocalizedLabels();
var panelColor = ResolvePanelBackgroundColor();
ApplyTypographyByBackground(panelColor);
if (!_studyEnabled)
{
TitleTextBlock.Text = L("study.widget.disabled_title", "自习功能未启用");
ModeTextBlock.Text = L("study.widget.disabled_hint", "请在设置中开启");
CurrentScoreTextBlock.Text = "--";
CurrentLabelTextBlock.Text = "";
return;
}
var snapshot = _studyAnalyticsService.GetSnapshot();
var realtimeScore = ComputeRealtimeScore(snapshot);
if (snapshot.DataMode == StudyDataMode.Realtime && realtimeScore is { } score)
{
@@ -676,6 +694,7 @@ public partial class StudyScoreOverviewWidget : UserControl, IDesktopComponentWi
{
var snapshot = _settingsService.Load();
_languageCode = _localizationService.NormalizeLanguageCode(snapshot.LanguageCode);
_studyEnabled = snapshot.StudyEnabled;
}
private void ApplyVariableFontFamily()

View File

@@ -64,6 +64,7 @@ public partial class StudySessionControlWidget : UserControl, IDesktopComponentW
private bool _isDisposed;
private bool _isCompactMode;
private bool _isUltraCompactMode;
private bool _studyEnabled = true;
private IDisposable? _monitoringLease;
private string? _transientMessage;
private DateTimeOffset _transientMessageExpireAt;
@@ -147,6 +148,13 @@ public partial class StudySessionControlWidget : UserControl, IDesktopComponentW
private void UpdateMonitoringLeaseState()
{
if (!_studyEnabled)
{
_monitoringLease?.Dispose();
_monitoringLease = null;
return;
}
var shouldMonitor = _isAttached && _isOnActivePage;
if (shouldMonitor)
{
@@ -193,11 +201,21 @@ public partial class StudySessionControlWidget : UserControl, IDesktopComponentW
private void RefreshVisual()
{
var snapshot = _studyAnalyticsService.GetSnapshot();
var now = DateTimeOffset.UtcNow;
var panelColor = ResolvePanelBackgroundColor();
ApplyTypographyByBackground(panelColor);
if (!_studyEnabled)
{
PrimaryTextBlock.Text = L("study.widget.disabled_title", "自习功能未启用");
SecondaryTextBlock.Text = L("study.widget.disabled_hint", "请在设置中开启");
ActionIcon.Kind = MaterialIconKind.Settings;
ApplyActionBadgeStyle(panelColor, Color.Parse("#FF9AA0A6"));
return;
}
var snapshot = _studyAnalyticsService.GetSnapshot();
if (_transientMessage is not null && now > _transientMessageExpireAt)
{
_transientMessage = null;
@@ -469,6 +487,7 @@ public partial class StudySessionControlWidget : UserControl, IDesktopComponentW
{
var snapshot = _settingsService.Load();
_languageCode = _localizationService.NormalizeLanguageCode(snapshot.LanguageCode);
_studyEnabled = snapshot.StudyEnabled;
}
private string L(string key, string fallback)

View File

@@ -25,7 +25,7 @@
TextTrimming="CharacterEllipsis" />
<Border Grid.Row="1"
CornerRadius="10"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Background="#1AFFFFFF"
BorderBrush="#26FFFFFF"
BorderThickness="1"
@@ -56,7 +56,7 @@
<Border x:Name="DialogCardBorder"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
CornerRadius="12"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
BorderThickness="1"
Padding="12">
<StackPanel Spacing="10">
@@ -80,12 +80,12 @@
<Button x:Name="DialogCancelButton"
Grid.Column="0"
Content="Cancel"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Height="30" />
<Button x:Name="DialogConfirmButton"
Grid.Column="1"
Content="Confirm"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Height="30" />
</Grid>
</StackPanel>

View File

@@ -58,6 +58,7 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW
private bool _isDisposed;
private bool _isCompactMode;
private bool _isUltraCompactMode;
private bool _studyEnabled = true;
private string? _loadingSessionId;
private HistoryDialogMode _dialogMode;
private string? _dialogSessionId;
@@ -179,6 +180,19 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW
TitleTextBlock.Text = L("study.session_history.title", "Session History");
TitleTextBlock.Foreground = CreateAdaptiveBrush(panelSamples, PrimaryColorCandidates, MinTextContrast);
if (!_studyEnabled)
{
if (_dialogMode != HistoryDialogMode.None)
{
CloseDialog();
}
SessionListPanel.Children.Clear();
StatusTextBlock.Text = L("study.widget.disabled_hint", "请在设置中开启");
StatusTextBlock.Foreground = CreateAdaptiveBrush(panelSamples, SecondaryColorCandidates, MinTextContrast);
return;
}
if (_transientStatus is not null && DateTimeOffset.UtcNow > _transientStatusExpireAt)
{
_transientStatus = null;
@@ -581,6 +595,7 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW
{
var snapshot = _settingsService.Load();
_languageCode = _localizationService.NormalizeLanguageCode(snapshot.LanguageCode);
_studyEnabled = snapshot.StudyEnabled;
}
private void UpdateAdaptiveLayout()

View File

@@ -22,7 +22,7 @@
Height="224"
HorizontalAlignment="Center"
VerticalAlignment="Center"
CornerRadius="32"
CornerRadius="{DynamicResource DesignCornerRadiusLg}"
BorderThickness="1">
<Grid ColumnDefinitions="96,2,*">
<Grid Grid.Column="0"
@@ -70,14 +70,14 @@
Grid.Row="0"
Height="3"
Width="18"
CornerRadius="2"
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
HorizontalAlignment="Left"
Background="#D0D6E1" />
<Border x:Name="ScaleMark2"
Grid.Row="1"
Height="3"
Width="16"
CornerRadius="2"
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
Margin="0,18,0,0"
HorizontalAlignment="Left"
Background="#D0D6E1" />
@@ -85,7 +85,7 @@
Grid.Row="2"
Height="3"
Width="14"
CornerRadius="2"
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
Margin="0,18,0,0"
HorizontalAlignment="Left"
Background="#D0D6E1" />
@@ -93,7 +93,7 @@
Grid.Row="3"
Height="3"
Width="12"
CornerRadius="2"
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
Margin="0,18,0,0"
HorizontalAlignment="Left"
Background="#D0D6E1" />

View File

@@ -32,12 +32,12 @@
</Border>
<Border x:Name="BackgroundTintLayer"
CornerRadius="30"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
ClipToBounds="True"
Opacity="0.16" />
<Border x:Name="BackgroundLightLayer"
CornerRadius="30"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
ClipToBounds="True"
Opacity="0.62">
<Border.Background>
@@ -54,7 +54,7 @@
</Border>
<Border x:Name="BackgroundShadeLayer"
CornerRadius="30"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
ClipToBounds="True"
Opacity="0.74">
<Border.Background>

View File

@@ -24,7 +24,7 @@
Background="#FFFFFF"
BorderBrush="#24000000"
BorderThickness="1"
CornerRadius="14"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
ClipToBounds="True">
<inking:InkCanvas x:Name="InkCanvas" />
</Border>
@@ -35,7 +35,7 @@
Background="#E6FFFFFF"
BorderBrush="#16000000"
BorderThickness="1"
CornerRadius="14"
CornerRadius="{DynamicResource DesignCornerRadiusSm}"
Padding="8,6">
<StackPanel x:Name="ToolbarButtonsPanel"
Orientation="Horizontal"
@@ -103,7 +103,7 @@
<Border Background="{DynamicResource AdaptiveSurfaceBaseBrush}"
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
BorderThickness="1"
CornerRadius="8"
CornerRadius="{DynamicResource DesignCornerRadiusXs}"
Padding="12">
<StackPanel Spacing="12">
<ColorView x:Name="InkColorPicker"

View File

@@ -8,10 +8,23 @@
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Classes="settings-page-container settings-page-animated">
<!-- 总开关 -->
<ui:SettingsExpander Classes="settings-expander-card"
Header="{Binding MasterSwitchHeader}"
Description="{Binding MasterSwitchDescription}">
<ui:SettingsExpander.IconSource>
<fi:SymbolIconSource Symbol="DataHistogram" />
</ui:SettingsExpander.IconSource>
<ui:SettingsExpander.Footer>
<ToggleSwitch IsChecked="{Binding StudyEnabled}" />
</ui:SettingsExpander.Footer>
</ui:SettingsExpander>
<!-- 噪音监测设置 -->
<ui:SettingsExpander Classes="settings-expander-card"
Header="{Binding NoiseMonitoringHeader}"
Description="{Binding NoiseMonitoringDescription}">
Description="{Binding NoiseMonitoringDescription}"
IsEnabled="{Binding StudyEnabled}">
<ui:SettingsExpander.IconSource>
<fi:SymbolIconSource Symbol="Mic" />
</ui:SettingsExpander.IconSource>
@@ -77,7 +90,8 @@
<!-- 专注计时设置 -->
<ui:SettingsExpander Classes="settings-expander-card"
Header="{Binding FocusTimerHeader}"
Description="{Binding FocusTimerDescription}">
Description="{Binding FocusTimerDescription}"
IsEnabled="{Binding StudyEnabled}">
<ui:SettingsExpander.IconSource>
<fi:SymbolIconSource Symbol="Timer" />
</ui:SettingsExpander.IconSource>
@@ -214,7 +228,8 @@
<!-- 提醒设置 -->
<ui:SettingsExpander Classes="settings-expander-card"
Header="{Binding AlertHeader}"
Description="{Binding AlertDescription}">
Description="{Binding AlertDescription}"
IsEnabled="{Binding StudyEnabled}">
<ui:SettingsExpander.IconSource>
<fi:SymbolIconSource Symbol="Alert" />
</ui:SettingsExpander.IconSource>
@@ -255,7 +270,8 @@
<!-- 显示设置 -->
<ui:SettingsExpander Classes="settings-expander-card"
Header="{Binding DisplayHeader}"
Description="{Binding DisplayDescription}">
Description="{Binding DisplayDescription}"
IsEnabled="{Binding StudyEnabled}">
<ui:SettingsExpander.IconSource>
<fi:SymbolIconSource Symbol="Eye" />
</ui:SettingsExpander.IconSource>