diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3ca60d7..f0ba330 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,6 +55,7 @@ jobs: needs: prepare runs-on: windows-latest strategy: + fail-fast: false matrix: arch: [x64, x86] name: Build_Windows_${{ matrix.arch }} @@ -136,14 +137,36 @@ jobs: exit 1 } - # Find Inno Setup compiler - $isccPath = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" - if (-not (Test-Path -Path $isccPath)) { - $isccPath = "C:\Program Files\Inno Setup 6\ISCC.exe" + # Find Inno Setup compiler (choco may install a shim in PATH) + $isccPath = $null + $isccCommand = Get-Command ISCC.exe -ErrorAction SilentlyContinue + if ($isccCommand) { + $isccPath = $isccCommand.Source } - - if (-not (Test-Path -Path $isccPath)) { - Write-Error "Inno Setup compiler not found at: $isccPath" + + $candidatePaths = @( + "C:\Program Files (x86)\Inno Setup 6\ISCC.exe", + "C:\Program Files\Inno Setup 6\ISCC.exe", + "$env:ChocolateyInstall\bin\ISCC.exe", + "$env:ChocolateyInstall\lib\innosetup\tools\ISCC.exe" + ) + + if (-not $isccPath) { + foreach ($candidate in $candidatePaths) { + if ($candidate -and (Test-Path -Path $candidate)) { + $isccPath = $candidate + break + } + } + } + + if (-not $isccPath) { + Write-Host "ISCC.exe was not found in PATH or known locations." + Write-Host "Checked locations:" + $candidatePaths | ForEach-Object { Write-Host " - $_" } + Write-Host "Chocolatey bin listing (if exists):" + Get-ChildItem "$env:ChocolateyInstall\bin" -Filter "*iscc*" -ErrorAction SilentlyContinue | Select-Object FullName + Write-Error "Inno Setup compiler not found." exit 1 } @@ -158,8 +181,8 @@ jobs: $compileArgs = @( "/DMyAppVersion=$version", - "/DPublishDir=$publishDir", - "/DMyOutputDir=$outputDir", + "/DPublishDir=`"$publishDir`"", + "/DMyOutputDir=`"$outputDir`"", "/DMyAppArch=$arch", $installerScript ) diff --git a/LanMountainDesktop/Views/Components/ExtendedWeatherWidget.axaml.cs b/LanMountainDesktop/Views/Components/ExtendedWeatherWidget.axaml.cs index 57c6206..2f794c5 100644 --- a/LanMountainDesktop/Views/Components/ExtendedWeatherWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/ExtendedWeatherWidget.axaml.cs @@ -14,12 +14,14 @@ using LanMountainDesktop.Services; namespace LanMountainDesktop.Views.Components; -public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget +public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget { private static readonly IWeatherInfoService DefaultWeatherInfoService = new XiaomiWeatherService(); private readonly DispatcherTimer _refreshTimer = new() { Interval = TimeSpan.FromMinutes(12) }; private readonly DispatcherTimer _animationTimer = new() { Interval = TimeSpan.FromMilliseconds(48) }; + private readonly ScaleTransform _backgroundMotionScaleTransform = new(1, 1); + private readonly TranslateTransform _backgroundMotionTranslateTransform = new(); private readonly AppSettingsService _settingsService = new(); private readonly LocalizationService _localizationService = new(); @@ -29,6 +31,7 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge private double _currentCellSize = 48; private double _phase; private bool _isAttached; + private bool _isOnActivePage = true; private bool _isRefreshing; private string _languageCode = "zh-CN"; private HyperOS3WeatherVisualKind _activeVisualKind = HyperOS3WeatherVisualKind.ClearDay; @@ -43,6 +46,7 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge public ExtendedWeatherWidget() { InitializeComponent(); + InitializeMotionTransform(); _hourlyTempBlocks = [ HourlyTemp0, HourlyTemp1, HourlyTemp2, HourlyTemp3, HourlyTemp4, HourlyTemp5 @@ -74,21 +78,9 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge ConfigureTextOverflowGuards(); _refreshTimer.Tick += OnRefreshTimerTick; _animationTimer.Tick += OnAnimationTick; - AttachedToVisualTree += (_, _) => - { - _isAttached = true; - _refreshTimer.Start(); - _animationTimer.Start(); - _ = RefreshWeatherAsync(false); - }; - DetachedFromVisualTree += (_, _) => - { - _isAttached = false; - _refreshTimer.Stop(); - _animationTimer.Stop(); - CancelRefresh(); - }; - SizeChanged += (_, _) => ApplyCellSize(_currentCellSize); + AttachedToVisualTree += OnAttachedToVisualTree; + DetachedFromVisualTree += OnDetachedFromVisualTree; + SizeChanged += OnSizeChanged; ApplyCellSize(_currentCellSize); ApplyVisualTheme(_activeVisualKind); ApplyFallback(); @@ -159,7 +151,20 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) { _weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; - if (_isAttached) + if (_isAttached && _isOnActivePage) + { + _ = RefreshWeatherAsync(false); + } + } + + public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode) + { + _ = isEditMode; + var wasOnActivePage = _isOnActivePage; + _isOnActivePage = isOnActivePage; + UpdateTimerState(); + + if (!wasOnActivePage && _isOnActivePage && _isAttached) { _ = RefreshWeatherAsync(false); } @@ -167,12 +172,34 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge private void OnTimeZoneChanged(object? sender, EventArgs e) { - if (_isAttached) + if (_isAttached && _isOnActivePage) { _ = RefreshWeatherAsync(false); } } + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) + { + _isAttached = true; + UpdateTimerState(); + if (_isOnActivePage) + { + _ = RefreshWeatherAsync(false); + } + } + + private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) + { + _isAttached = false; + UpdateTimerState(); + CancelRefresh(); + } + + private void OnSizeChanged(object? sender, SizeChangedEventArgs e) + { + ApplyCellSize(_currentCellSize); + } + private async void OnRefreshTimerTick(object? sender, EventArgs e) { await RefreshWeatherAsync(false); @@ -180,18 +207,16 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge private void OnAnimationTick(object? sender, EventArgs e) { + if (!_isAttached || !_isOnActivePage) + { + return; + } + _phase += 0.018; if (_phase > Math.PI * 2) _phase -= Math.PI * 2; var sin = Math.Sin(_phase); var cos = Math.Cos(_phase * 0.83); - BackgroundMotionLayer.RenderTransform = new TransformGroup - { - Children = new Transforms - { - new ScaleTransform(1.05 + (sin * 0.01), 1.05 + (sin * 0.01)), - new TranslateTransform(sin * 7.0, cos * 5.0) - } - }; + SetMotionTransform(sin * 7.0, cos * 5.0, 1.05 + (sin * 0.01)); BackgroundMotionLayer.Opacity = Math.Clamp(0.27 + (cos * 0.05), 0.10, 0.90); BackgroundLightLayer.Opacity = Math.Clamp(0.62 + (sin * 0.06), 0.20, 0.95); BackgroundShadeLayer.Opacity = Math.Clamp(0.80 + (cos * 0.03), 0.45, 0.95); @@ -199,7 +224,7 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge private async Task RefreshWeatherAsync(bool forceRefresh) { - if (!_isAttached || _isRefreshing) + if (!_isAttached || !_isOnActivePage || _isRefreshing) { return; } @@ -821,6 +846,48 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge private string L(string key, string fallback) => _localizationService.GetString(_languageCode, key, fallback); + private void InitializeMotionTransform() + { + BackgroundMotionLayer.RenderTransform = new TransformGroup + { + Children = new Transforms + { + _backgroundMotionScaleTransform, + _backgroundMotionTranslateTransform + } + }; + SetMotionTransform(0, 0, 1.05); + } + + private void SetMotionTransform(double translateX, double translateY, double scale) + { + _backgroundMotionScaleTransform.ScaleX = scale; + _backgroundMotionScaleTransform.ScaleY = scale; + _backgroundMotionTranslateTransform.X = translateX; + _backgroundMotionTranslateTransform.Y = translateY; + } + + private void UpdateTimerState() + { + if (_isAttached && _isOnActivePage) + { + if (!_refreshTimer.IsEnabled) + { + _refreshTimer.Start(); + } + + if (!_animationTimer.IsEnabled) + { + _animationTimer.Start(); + } + + return; + } + + _refreshTimer.Stop(); + _animationTimer.Stop(); + } + private void CancelRefresh() { var cts = Interlocked.Exchange(ref _refreshCts, null); diff --git a/LanMountainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs b/LanMountainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs index ed89c92..bcc44a3 100644 --- a/LanMountainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs @@ -16,7 +16,7 @@ using LanMountainDesktop.Services; namespace LanMountainDesktop.Views.Components; -public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget +public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget { private enum WeatherVisualKind { @@ -99,6 +99,8 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, private readonly List _particleVisuals = new(); private readonly List _particleStates = new(); private readonly Random _particleRandom = new(); + private readonly ScaleTransform _backgroundMotionScaleTransform = new(1, 1); + private readonly TranslateTransform _backgroundMotionTranslateTransform = new(); private IWeatherInfoService _weatherInfoService = DefaultWeatherInfoService; private TimeZoneService? _timeZoneService; @@ -110,6 +112,7 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, private double _animationPhase; private int _activeParticleCount; private bool _isAttached; + private bool _isOnActivePage = true; private bool _isRefreshing; private readonly TextBlock[] _hourlyTimeBlocks; private readonly Image[] _hourlyIconBlocks; @@ -118,6 +121,7 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, public HourlyWeatherWidget() { InitializeComponent(); + InitializeMotionTransform(); _hourlyTimeBlocks = [ HourlyTime0, HourlyTime1, HourlyTime2, HourlyTime3, HourlyTime4, HourlyTime5 @@ -200,7 +204,20 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) { _weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; - if (_isAttached) + if (_isAttached && _isOnActivePage) + { + _ = RefreshWeatherAsync(forceRefresh: false); + } + } + + public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode) + { + _ = isEditMode; + var wasOnActivePage = _isOnActivePage; + _isOnActivePage = isOnActivePage; + UpdateTimerState(); + + if (!wasOnActivePage && _isOnActivePage && _isAttached) { _ = RefreshWeatherAsync(forceRefresh: false); } @@ -231,16 +248,17 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = true; - _refreshTimer.Start(); - _backgroundAnimationTimer.Start(); - _ = RefreshWeatherAsync(forceRefresh: false); + UpdateTimerState(); + if (_isOnActivePage) + { + _ = RefreshWeatherAsync(forceRefresh: false); + } } private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = false; - _refreshTimer.Stop(); - _backgroundAnimationTimer.Stop(); + UpdateTimerState(); CancelRefreshRequest(); } @@ -257,7 +275,7 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, private void OnBackgroundAnimationTick(object? sender, EventArgs e) { - if (!_isAttached) + if (!_isAttached || !_isOnActivePage) { return; } @@ -320,7 +338,7 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, private async Task RefreshWeatherAsync(bool forceRefresh) { - if (!_isAttached || _isRefreshing) + if (!_isAttached || !_isOnActivePage || _isRefreshing) { return; } @@ -1339,15 +1357,43 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, private void SetMotionTransform(double translateX, double translateY, double scale) { - var group = new TransformGroup + _backgroundMotionScaleTransform.ScaleX = scale; + _backgroundMotionScaleTransform.ScaleY = scale; + _backgroundMotionTranslateTransform.X = translateX; + _backgroundMotionTranslateTransform.Y = translateY; + } + + private void InitializeMotionTransform() + { + BackgroundMotionLayer.RenderTransform = new TransformGroup { Children = new Transforms { - new ScaleTransform(scale, scale), - new TranslateTransform(translateX, translateY) + _backgroundMotionScaleTransform, + _backgroundMotionTranslateTransform } }; - BackgroundMotionLayer.RenderTransform = group; + } + + private void UpdateTimerState() + { + if (_isAttached && _isOnActivePage) + { + if (!_refreshTimer.IsEnabled) + { + _refreshTimer.Start(); + } + + if (!_backgroundAnimationTimer.IsEnabled) + { + _backgroundAnimationTimer.Start(); + } + + return; + } + + _refreshTimer.Stop(); + _backgroundAnimationTimer.Stop(); } private void InitializeParticleVisuals() diff --git a/LanMountainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs b/LanMountainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs index 3b37a43..da809c0 100644 --- a/LanMountainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs @@ -14,7 +14,7 @@ using LanMountainDesktop.Services; namespace LanMountainDesktop.Views.Components; -public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget +public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget { private enum WeatherVisualKind { @@ -97,6 +97,8 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge private readonly List _particleVisuals = new(); private readonly List _particleStates = new(); private readonly Random _particleRandom = new(); + private readonly ScaleTransform _backgroundMotionScaleTransform = new(1, 1); + private readonly TranslateTransform _backgroundMotionTranslateTransform = new(); private IWeatherInfoService _weatherInfoService = DefaultWeatherInfoService; private TimeZoneService? _timeZoneService; @@ -108,6 +110,7 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge private double _animationPhase; private int _activeParticleCount; private bool _isAttached; + private bool _isOnActivePage = true; private bool _isRefreshing; private readonly TextBlock[] _hourlyTimeBlocks; private readonly Image[] _hourlyIconBlocks; @@ -116,6 +119,7 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge public MultiDayWeatherWidget() { InitializeComponent(); + InitializeMotionTransform(); _hourlyTimeBlocks = [ HourlyTime0, HourlyTime1, HourlyTime2, HourlyTime3, HourlyTime4 @@ -198,7 +202,20 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) { _weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; - if (_isAttached) + if (_isAttached && _isOnActivePage) + { + _ = RefreshWeatherAsync(forceRefresh: false); + } + } + + public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode) + { + _ = isEditMode; + var wasOnActivePage = _isOnActivePage; + _isOnActivePage = isOnActivePage; + UpdateTimerState(); + + if (!wasOnActivePage && _isOnActivePage && _isAttached) { _ = RefreshWeatherAsync(forceRefresh: false); } @@ -229,16 +246,17 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = true; - _refreshTimer.Start(); - _backgroundAnimationTimer.Start(); - _ = RefreshWeatherAsync(forceRefresh: false); + UpdateTimerState(); + if (_isOnActivePage) + { + _ = RefreshWeatherAsync(forceRefresh: false); + } } private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = false; - _refreshTimer.Stop(); - _backgroundAnimationTimer.Stop(); + UpdateTimerState(); CancelRefreshRequest(); } @@ -255,7 +273,7 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge private void OnBackgroundAnimationTick(object? sender, EventArgs e) { - if (!_isAttached) + if (!_isAttached || !_isOnActivePage) { return; } @@ -318,7 +336,7 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge private async Task RefreshWeatherAsync(bool forceRefresh) { - if (!_isAttached || _isRefreshing) + if (!_isAttached || !_isOnActivePage || _isRefreshing) { return; } @@ -1189,15 +1207,43 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge private void SetMotionTransform(double translateX, double translateY, double scale) { - var group = new TransformGroup + _backgroundMotionScaleTransform.ScaleX = scale; + _backgroundMotionScaleTransform.ScaleY = scale; + _backgroundMotionTranslateTransform.X = translateX; + _backgroundMotionTranslateTransform.Y = translateY; + } + + private void InitializeMotionTransform() + { + BackgroundMotionLayer.RenderTransform = new TransformGroup { Children = new Transforms { - new ScaleTransform(scale, scale), - new TranslateTransform(translateX, translateY) + _backgroundMotionScaleTransform, + _backgroundMotionTranslateTransform } }; - BackgroundMotionLayer.RenderTransform = group; + } + + private void UpdateTimerState() + { + if (_isAttached && _isOnActivePage) + { + if (!_refreshTimer.IsEnabled) + { + _refreshTimer.Start(); + } + + if (!_backgroundAnimationTimer.IsEnabled) + { + _backgroundAnimationTimer.Start(); + } + + return; + } + + _refreshTimer.Stop(); + _backgroundAnimationTimer.Stop(); } private void InitializeParticleVisuals() diff --git a/LanMountainDesktop/Views/Components/MusicControlWidget.axaml.cs b/LanMountainDesktop/Views/Components/MusicControlWidget.axaml.cs index d8073bf..91b96a7 100644 --- a/LanMountainDesktop/Views/Components/MusicControlWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/MusicControlWidget.axaml.cs @@ -17,7 +17,7 @@ using LanMountainDesktop.Theme; namespace LanMountainDesktop.Views.Components; -public partial class MusicControlWidget : UserControl, IDesktopComponentWidget +public partial class MusicControlWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget { private const Symbol PlaySymbol = Symbol.Play; private const Symbol PauseSymbol = Symbol.Pause; @@ -38,6 +38,7 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget private string _languageCode = "zh-CN"; private double _currentCellSize = 48; private bool _isAttached; + private bool _isOnActivePage = true; private bool _isRefreshing; private bool _isExecutingCommand; private double _progressRatio; @@ -126,17 +127,33 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget UpdateProgressVisual(_progressRatio, _isProgressIndeterminate); } + public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode) + { + _ = isEditMode; + var wasOnActivePage = _isOnActivePage; + _isOnActivePage = isOnActivePage; + UpdateRefreshTimerState(); + + if (!wasOnActivePage && _isOnActivePage && _isAttached) + { + _ = RefreshStateAsync(); + } + } + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = true; - _refreshTimer.Start(); - _ = RefreshStateAsync(); + UpdateRefreshTimerState(); + if (_isOnActivePage) + { + _ = RefreshStateAsync(); + } } private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = false; - _refreshTimer.Stop(); + UpdateRefreshTimerState(); CancelRefreshRequest(); DisposeCoverBitmap(); } @@ -211,7 +228,7 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget private async Task RefreshStateAsync() { - if (!_isAttached || _isRefreshing) + if (!_isAttached || !_isOnActivePage || _isRefreshing) { return; } @@ -257,6 +274,21 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget } } + private void UpdateRefreshTimerState() + { + if (_isAttached && _isOnActivePage) + { + if (!_refreshTimer.IsEnabled) + { + _refreshTimer.Start(); + } + + return; + } + + _refreshTimer.Stop(); + } + private void ApplyState(MusicPlaybackState state) { var hasMediaSession = state.IsSupported && state.HasSession; diff --git a/LanMountainDesktop/Views/Components/RecordingWidget.axaml.cs b/LanMountainDesktop/Views/Components/RecordingWidget.axaml.cs index 9bd2081..123c3dc 100644 --- a/LanMountainDesktop/Views/Components/RecordingWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/RecordingWidget.axaml.cs @@ -14,7 +14,7 @@ using LanMountainDesktop.Services; namespace LanMountainDesktop.Views.Components; -public partial class RecordingWidget : UserControl, IDesktopComponentWidget +public partial class RecordingWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget { private const int WaveBarCount = 22; @@ -34,6 +34,7 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget private string _lastSavedFilePath = string.Empty; private double _currentCellSize = 48; private bool _isAttached; + private bool _isOnActivePage = true; private bool _pausedStudyMonitoringForRecording; public RecordingWidget() @@ -106,10 +107,24 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget UpdateWaveformVisual(); } + public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode) + { + _ = isEditMode; + var wasOnActivePage = _isOnActivePage; + _isOnActivePage = isOnActivePage; + UpdateUiTimerState(); + + if (!wasOnActivePage && _isOnActivePage && _isAttached) + { + ReloadLanguageCode(); + RefreshVisual(); + } + } + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = true; - _uiTimer.Start(); + UpdateUiTimerState(); ReloadLanguageCode(); RefreshVisual(); } @@ -117,7 +132,7 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = false; - _uiTimer.Stop(); + UpdateUiTimerState(); var snapshot = _audioRecorderService.GetSnapshot(); if (snapshot.State is not AudioRecorderRuntimeState.Recording and not AudioRecorderRuntimeState.Paused) @@ -133,7 +148,7 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget private void OnUiTick(object? sender, EventArgs e) { - if (!_isAttached) + if (!_isAttached || !_isOnActivePage) { return; } @@ -141,6 +156,21 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget RefreshVisual(); } + private void UpdateUiTimerState() + { + if (_isAttached && _isOnActivePage) + { + if (!_uiTimer.IsEnabled) + { + _uiTimer.Start(); + } + + return; + } + + _uiTimer.Stop(); + } + private void OnDiscardButtonPointerPressed(object? sender, PointerPressedEventArgs e) { if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) diff --git a/LanMountainDesktop/Views/Components/WeatherWidget.axaml.cs b/LanMountainDesktop/Views/Components/WeatherWidget.axaml.cs index 405ce40..2e66f05 100644 --- a/LanMountainDesktop/Views/Components/WeatherWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/WeatherWidget.axaml.cs @@ -16,7 +16,7 @@ using LanMountainDesktop.Services; namespace LanMountainDesktop.Views.Components; -public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget +public partial class WeatherWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget { private enum WeatherVisualKind { @@ -93,6 +93,8 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime private readonly List _particleVisuals = new(); private readonly List _particleStates = new(); private readonly Random _particleRandom = new(); + private readonly ScaleTransform _backgroundMotionScaleTransform = new(1, 1); + private readonly TranslateTransform _backgroundMotionTranslateTransform = new(); private IWeatherInfoService _weatherInfoService = DefaultWeatherInfoService; private TimeZoneService? _timeZoneService; @@ -104,11 +106,13 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime private double _animationPhase; private int _activeParticleCount; private bool _isAttached; + private bool _isOnActivePage = true; private bool _isRefreshing; public WeatherWidget() { InitializeComponent(); + InitializeMotionTransform(); _refreshTimer.Tick += OnRefreshTimerTick; _backgroundAnimationTimer.Tick += OnBackgroundAnimationTick; @@ -143,7 +147,20 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) { _weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; - if (_isAttached) + if (_isAttached && _isOnActivePage) + { + _ = RefreshWeatherAsync(forceRefresh: false); + } + } + + public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode) + { + _ = isEditMode; + var wasOnActivePage = _isOnActivePage; + _isOnActivePage = isOnActivePage; + UpdateTimerState(); + + if (!wasOnActivePage && _isOnActivePage && _isAttached) { _ = RefreshWeatherAsync(forceRefresh: false); } @@ -176,16 +193,17 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = true; - _refreshTimer.Start(); - _backgroundAnimationTimer.Start(); - _ = RefreshWeatherAsync(forceRefresh: false); + UpdateTimerState(); + if (_isOnActivePage) + { + _ = RefreshWeatherAsync(forceRefresh: false); + } } private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { _isAttached = false; - _refreshTimer.Stop(); - _backgroundAnimationTimer.Stop(); + UpdateTimerState(); CancelRefreshRequest(); } @@ -202,7 +220,7 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime private void OnBackgroundAnimationTick(object? sender, EventArgs e) { - if (!_isAttached) + if (!_isAttached || !_isOnActivePage) { return; } @@ -265,7 +283,7 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime private async Task RefreshWeatherAsync(bool forceRefresh) { - if (!_isAttached || _isRefreshing) + if (!_isAttached || !_isOnActivePage || _isRefreshing) { return; } @@ -980,15 +998,43 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime private void SetMotionTransform(double translateX, double translateY, double scale) { - var group = new TransformGroup + _backgroundMotionScaleTransform.ScaleX = scale; + _backgroundMotionScaleTransform.ScaleY = scale; + _backgroundMotionTranslateTransform.X = translateX; + _backgroundMotionTranslateTransform.Y = translateY; + } + + private void InitializeMotionTransform() + { + BackgroundMotionLayer.RenderTransform = new TransformGroup { Children = new Transforms { - new ScaleTransform(scale, scale), - new TranslateTransform(translateX, translateY) + _backgroundMotionScaleTransform, + _backgroundMotionTranslateTransform } }; - BackgroundMotionLayer.RenderTransform = group; + } + + private void UpdateTimerState() + { + if (_isAttached && _isOnActivePage) + { + if (!_refreshTimer.IsEnabled) + { + _refreshTimer.Start(); + } + + if (!_backgroundAnimationTimer.IsEnabled) + { + _backgroundAnimationTimer.Start(); + } + + return; + } + + _refreshTimer.Stop(); + _backgroundAnimationTimer.Stop(); } private void InitializeParticleVisuals() diff --git a/LanMountainDesktop/Views/MainWindow.Settings.cs b/LanMountainDesktop/Views/MainWindow.Settings.cs index 81a1296..825e9a0 100644 --- a/LanMountainDesktop/Views/MainWindow.Settings.cs +++ b/LanMountainDesktop/Views/MainWindow.Settings.cs @@ -1906,7 +1906,7 @@ public partial class MainWindow } SettingsPage.IsVisible = false; - }, TimeSpan.FromMilliseconds(200)); + }, TimeSpan.FromMilliseconds(SettingsTransitionDurationMs)); } private void InitializeSettingsIcons()