动画优化
This commit is contained in:
lincube
2026-03-05 14:03:35 +08:00
parent 2e49602bff
commit d182925b58
8 changed files with 375 additions and 85 deletions

View File

@@ -55,6 +55,7 @@ jobs:
needs: prepare needs: prepare
runs-on: windows-latest runs-on: windows-latest
strategy: strategy:
fail-fast: false
matrix: matrix:
arch: [x64, x86] arch: [x64, x86]
name: Build_Windows_${{ matrix.arch }} name: Build_Windows_${{ matrix.arch }}
@@ -136,14 +137,36 @@ jobs:
exit 1 exit 1
} }
# Find Inno Setup compiler # Find Inno Setup compiler (choco may install a shim in PATH)
$isccPath = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" $isccPath = $null
if (-not (Test-Path -Path $isccPath)) { $isccCommand = Get-Command ISCC.exe -ErrorAction SilentlyContinue
$isccPath = "C:\Program Files\Inno Setup 6\ISCC.exe" if ($isccCommand) {
$isccPath = $isccCommand.Source
} }
if (-not (Test-Path -Path $isccPath)) { $candidatePaths = @(
Write-Error "Inno Setup compiler not found at: $isccPath" "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 exit 1
} }
@@ -158,8 +181,8 @@ jobs:
$compileArgs = @( $compileArgs = @(
"/DMyAppVersion=$version", "/DMyAppVersion=$version",
"/DPublishDir=$publishDir", "/DPublishDir=`"$publishDir`"",
"/DMyOutputDir=$outputDir", "/DMyOutputDir=`"$outputDir`"",
"/DMyAppArch=$arch", "/DMyAppArch=$arch",
$installerScript $installerScript
) )

View File

@@ -14,12 +14,14 @@ using LanMountainDesktop.Services;
namespace LanMountainDesktop.Views.Components; 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 static readonly IWeatherInfoService DefaultWeatherInfoService = new XiaomiWeatherService();
private readonly DispatcherTimer _refreshTimer = new() { Interval = TimeSpan.FromMinutes(12) }; private readonly DispatcherTimer _refreshTimer = new() { Interval = TimeSpan.FromMinutes(12) };
private readonly DispatcherTimer _animationTimer = new() { Interval = TimeSpan.FromMilliseconds(48) }; 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 AppSettingsService _settingsService = new();
private readonly LocalizationService _localizationService = new(); private readonly LocalizationService _localizationService = new();
@@ -29,6 +31,7 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge
private double _currentCellSize = 48; private double _currentCellSize = 48;
private double _phase; private double _phase;
private bool _isAttached; private bool _isAttached;
private bool _isOnActivePage = true;
private bool _isRefreshing; private bool _isRefreshing;
private string _languageCode = "zh-CN"; private string _languageCode = "zh-CN";
private HyperOS3WeatherVisualKind _activeVisualKind = HyperOS3WeatherVisualKind.ClearDay; private HyperOS3WeatherVisualKind _activeVisualKind = HyperOS3WeatherVisualKind.ClearDay;
@@ -43,6 +46,7 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge
public ExtendedWeatherWidget() public ExtendedWeatherWidget()
{ {
InitializeComponent(); InitializeComponent();
InitializeMotionTransform();
_hourlyTempBlocks = _hourlyTempBlocks =
[ [
HourlyTemp0, HourlyTemp1, HourlyTemp2, HourlyTemp3, HourlyTemp4, HourlyTemp5 HourlyTemp0, HourlyTemp1, HourlyTemp2, HourlyTemp3, HourlyTemp4, HourlyTemp5
@@ -74,21 +78,9 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge
ConfigureTextOverflowGuards(); ConfigureTextOverflowGuards();
_refreshTimer.Tick += OnRefreshTimerTick; _refreshTimer.Tick += OnRefreshTimerTick;
_animationTimer.Tick += OnAnimationTick; _animationTimer.Tick += OnAnimationTick;
AttachedToVisualTree += (_, _) => AttachedToVisualTree += OnAttachedToVisualTree;
{ DetachedFromVisualTree += OnDetachedFromVisualTree;
_isAttached = true; SizeChanged += OnSizeChanged;
_refreshTimer.Start();
_animationTimer.Start();
_ = RefreshWeatherAsync(false);
};
DetachedFromVisualTree += (_, _) =>
{
_isAttached = false;
_refreshTimer.Stop();
_animationTimer.Stop();
CancelRefresh();
};
SizeChanged += (_, _) => ApplyCellSize(_currentCellSize);
ApplyCellSize(_currentCellSize); ApplyCellSize(_currentCellSize);
ApplyVisualTheme(_activeVisualKind); ApplyVisualTheme(_activeVisualKind);
ApplyFallback(); ApplyFallback();
@@ -159,7 +151,20 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
{ {
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; _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); _ = RefreshWeatherAsync(false);
} }
@@ -167,12 +172,34 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge
private void OnTimeZoneChanged(object? sender, EventArgs e) private void OnTimeZoneChanged(object? sender, EventArgs e)
{ {
if (_isAttached) if (_isAttached && _isOnActivePage)
{ {
_ = RefreshWeatherAsync(false); _ = 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) private async void OnRefreshTimerTick(object? sender, EventArgs e)
{ {
await RefreshWeatherAsync(false); await RefreshWeatherAsync(false);
@@ -180,18 +207,16 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge
private void OnAnimationTick(object? sender, EventArgs e) private void OnAnimationTick(object? sender, EventArgs e)
{ {
if (!_isAttached || !_isOnActivePage)
{
return;
}
_phase += 0.018; _phase += 0.018;
if (_phase > Math.PI * 2) _phase -= Math.PI * 2; if (_phase > Math.PI * 2) _phase -= Math.PI * 2;
var sin = Math.Sin(_phase); var sin = Math.Sin(_phase);
var cos = Math.Cos(_phase * 0.83); var cos = Math.Cos(_phase * 0.83);
BackgroundMotionLayer.RenderTransform = new TransformGroup SetMotionTransform(sin * 7.0, cos * 5.0, 1.05 + (sin * 0.01));
{
Children = new Transforms
{
new ScaleTransform(1.05 + (sin * 0.01), 1.05 + (sin * 0.01)),
new TranslateTransform(sin * 7.0, cos * 5.0)
}
};
BackgroundMotionLayer.Opacity = Math.Clamp(0.27 + (cos * 0.05), 0.10, 0.90); 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); 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); 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) private async Task RefreshWeatherAsync(bool forceRefresh)
{ {
if (!_isAttached || _isRefreshing) if (!_isAttached || !_isOnActivePage || _isRefreshing)
{ {
return; return;
} }
@@ -821,6 +846,48 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge
private string L(string key, string fallback) => _localizationService.GetString(_languageCode, key, fallback); 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() private void CancelRefresh()
{ {
var cts = Interlocked.Exchange(ref _refreshCts, null); var cts = Interlocked.Exchange(ref _refreshCts, null);

View File

@@ -16,7 +16,7 @@ using LanMountainDesktop.Services;
namespace LanMountainDesktop.Views.Components; namespace LanMountainDesktop.Views.Components;
public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget
{ {
private enum WeatherVisualKind private enum WeatherVisualKind
{ {
@@ -99,6 +99,8 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget,
private readonly List<Border> _particleVisuals = new(); private readonly List<Border> _particleVisuals = new();
private readonly List<ParticleState> _particleStates = new(); private readonly List<ParticleState> _particleStates = new();
private readonly Random _particleRandom = new(); private readonly Random _particleRandom = new();
private readonly ScaleTransform _backgroundMotionScaleTransform = new(1, 1);
private readonly TranslateTransform _backgroundMotionTranslateTransform = new();
private IWeatherInfoService _weatherInfoService = DefaultWeatherInfoService; private IWeatherInfoService _weatherInfoService = DefaultWeatherInfoService;
private TimeZoneService? _timeZoneService; private TimeZoneService? _timeZoneService;
@@ -110,6 +112,7 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget,
private double _animationPhase; private double _animationPhase;
private int _activeParticleCount; private int _activeParticleCount;
private bool _isAttached; private bool _isAttached;
private bool _isOnActivePage = true;
private bool _isRefreshing; private bool _isRefreshing;
private readonly TextBlock[] _hourlyTimeBlocks; private readonly TextBlock[] _hourlyTimeBlocks;
private readonly Image[] _hourlyIconBlocks; private readonly Image[] _hourlyIconBlocks;
@@ -118,6 +121,7 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget,
public HourlyWeatherWidget() public HourlyWeatherWidget()
{ {
InitializeComponent(); InitializeComponent();
InitializeMotionTransform();
_hourlyTimeBlocks = _hourlyTimeBlocks =
[ [
HourlyTime0, HourlyTime1, HourlyTime2, HourlyTime3, HourlyTime4, HourlyTime5 HourlyTime0, HourlyTime1, HourlyTime2, HourlyTime3, HourlyTime4, HourlyTime5
@@ -200,7 +204,20 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget,
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
{ {
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; _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); _ = RefreshWeatherAsync(forceRefresh: false);
} }
@@ -231,16 +248,17 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget,
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = true; _isAttached = true;
_refreshTimer.Start(); UpdateTimerState();
_backgroundAnimationTimer.Start(); if (_isOnActivePage)
{
_ = RefreshWeatherAsync(forceRefresh: false); _ = RefreshWeatherAsync(forceRefresh: false);
} }
}
private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = false; _isAttached = false;
_refreshTimer.Stop(); UpdateTimerState();
_backgroundAnimationTimer.Stop();
CancelRefreshRequest(); CancelRefreshRequest();
} }
@@ -257,7 +275,7 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget,
private void OnBackgroundAnimationTick(object? sender, EventArgs e) private void OnBackgroundAnimationTick(object? sender, EventArgs e)
{ {
if (!_isAttached) if (!_isAttached || !_isOnActivePage)
{ {
return; return;
} }
@@ -320,7 +338,7 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget,
private async Task RefreshWeatherAsync(bool forceRefresh) private async Task RefreshWeatherAsync(bool forceRefresh)
{ {
if (!_isAttached || _isRefreshing) if (!_isAttached || !_isOnActivePage || _isRefreshing)
{ {
return; return;
} }
@@ -1339,15 +1357,43 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget,
private void SetMotionTransform(double translateX, double translateY, double scale) 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 Children = new Transforms
{ {
new ScaleTransform(scale, scale), _backgroundMotionScaleTransform,
new TranslateTransform(translateX, translateY) _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() private void InitializeParticleVisuals()

View File

@@ -14,7 +14,7 @@ using LanMountainDesktop.Services;
namespace LanMountainDesktop.Views.Components; namespace LanMountainDesktop.Views.Components;
public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget
{ {
private enum WeatherVisualKind private enum WeatherVisualKind
{ {
@@ -97,6 +97,8 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge
private readonly List<Border> _particleVisuals = new(); private readonly List<Border> _particleVisuals = new();
private readonly List<ParticleState> _particleStates = new(); private readonly List<ParticleState> _particleStates = new();
private readonly Random _particleRandom = new(); private readonly Random _particleRandom = new();
private readonly ScaleTransform _backgroundMotionScaleTransform = new(1, 1);
private readonly TranslateTransform _backgroundMotionTranslateTransform = new();
private IWeatherInfoService _weatherInfoService = DefaultWeatherInfoService; private IWeatherInfoService _weatherInfoService = DefaultWeatherInfoService;
private TimeZoneService? _timeZoneService; private TimeZoneService? _timeZoneService;
@@ -108,6 +110,7 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge
private double _animationPhase; private double _animationPhase;
private int _activeParticleCount; private int _activeParticleCount;
private bool _isAttached; private bool _isAttached;
private bool _isOnActivePage = true;
private bool _isRefreshing; private bool _isRefreshing;
private readonly TextBlock[] _hourlyTimeBlocks; private readonly TextBlock[] _hourlyTimeBlocks;
private readonly Image[] _hourlyIconBlocks; private readonly Image[] _hourlyIconBlocks;
@@ -116,6 +119,7 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge
public MultiDayWeatherWidget() public MultiDayWeatherWidget()
{ {
InitializeComponent(); InitializeComponent();
InitializeMotionTransform();
_hourlyTimeBlocks = _hourlyTimeBlocks =
[ [
HourlyTime0, HourlyTime1, HourlyTime2, HourlyTime3, HourlyTime4 HourlyTime0, HourlyTime1, HourlyTime2, HourlyTime3, HourlyTime4
@@ -198,7 +202,20 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
{ {
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; _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); _ = RefreshWeatherAsync(forceRefresh: false);
} }
@@ -229,16 +246,17 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = true; _isAttached = true;
_refreshTimer.Start(); UpdateTimerState();
_backgroundAnimationTimer.Start(); if (_isOnActivePage)
{
_ = RefreshWeatherAsync(forceRefresh: false); _ = RefreshWeatherAsync(forceRefresh: false);
} }
}
private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = false; _isAttached = false;
_refreshTimer.Stop(); UpdateTimerState();
_backgroundAnimationTimer.Stop();
CancelRefreshRequest(); CancelRefreshRequest();
} }
@@ -255,7 +273,7 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge
private void OnBackgroundAnimationTick(object? sender, EventArgs e) private void OnBackgroundAnimationTick(object? sender, EventArgs e)
{ {
if (!_isAttached) if (!_isAttached || !_isOnActivePage)
{ {
return; return;
} }
@@ -318,7 +336,7 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge
private async Task RefreshWeatherAsync(bool forceRefresh) private async Task RefreshWeatherAsync(bool forceRefresh)
{ {
if (!_isAttached || _isRefreshing) if (!_isAttached || !_isOnActivePage || _isRefreshing)
{ {
return; return;
} }
@@ -1189,15 +1207,43 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge
private void SetMotionTransform(double translateX, double translateY, double scale) 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 Children = new Transforms
{ {
new ScaleTransform(scale, scale), _backgroundMotionScaleTransform,
new TranslateTransform(translateX, translateY) _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() private void InitializeParticleVisuals()

View File

@@ -17,7 +17,7 @@ using LanMountainDesktop.Theme;
namespace LanMountainDesktop.Views.Components; 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 PlaySymbol = Symbol.Play;
private const Symbol PauseSymbol = Symbol.Pause; private const Symbol PauseSymbol = Symbol.Pause;
@@ -38,6 +38,7 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget
private string _languageCode = "zh-CN"; private string _languageCode = "zh-CN";
private double _currentCellSize = 48; private double _currentCellSize = 48;
private bool _isAttached; private bool _isAttached;
private bool _isOnActivePage = true;
private bool _isRefreshing; private bool _isRefreshing;
private bool _isExecutingCommand; private bool _isExecutingCommand;
private double _progressRatio; private double _progressRatio;
@@ -126,17 +127,33 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget
UpdateProgressVisual(_progressRatio, _isProgressIndeterminate); 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) private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = true; _isAttached = true;
_refreshTimer.Start(); UpdateRefreshTimerState();
if (_isOnActivePage)
{
_ = RefreshStateAsync(); _ = RefreshStateAsync();
} }
}
private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = false; _isAttached = false;
_refreshTimer.Stop(); UpdateRefreshTimerState();
CancelRefreshRequest(); CancelRefreshRequest();
DisposeCoverBitmap(); DisposeCoverBitmap();
} }
@@ -211,7 +228,7 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget
private async Task RefreshStateAsync() private async Task RefreshStateAsync()
{ {
if (!_isAttached || _isRefreshing) if (!_isAttached || !_isOnActivePage || _isRefreshing)
{ {
return; 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) private void ApplyState(MusicPlaybackState state)
{ {
var hasMediaSession = state.IsSupported && state.HasSession; var hasMediaSession = state.IsSupported && state.HasSession;

View File

@@ -14,7 +14,7 @@ using LanMountainDesktop.Services;
namespace LanMountainDesktop.Views.Components; namespace LanMountainDesktop.Views.Components;
public partial class RecordingWidget : UserControl, IDesktopComponentWidget public partial class RecordingWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget
{ {
private const int WaveBarCount = 22; private const int WaveBarCount = 22;
@@ -34,6 +34,7 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget
private string _lastSavedFilePath = string.Empty; private string _lastSavedFilePath = string.Empty;
private double _currentCellSize = 48; private double _currentCellSize = 48;
private bool _isAttached; private bool _isAttached;
private bool _isOnActivePage = true;
private bool _pausedStudyMonitoringForRecording; private bool _pausedStudyMonitoringForRecording;
public RecordingWidget() public RecordingWidget()
@@ -106,10 +107,24 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget
UpdateWaveformVisual(); 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) private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = true; _isAttached = true;
_uiTimer.Start(); UpdateUiTimerState();
ReloadLanguageCode(); ReloadLanguageCode();
RefreshVisual(); RefreshVisual();
} }
@@ -117,7 +132,7 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget
private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = false; _isAttached = false;
_uiTimer.Stop(); UpdateUiTimerState();
var snapshot = _audioRecorderService.GetSnapshot(); var snapshot = _audioRecorderService.GetSnapshot();
if (snapshot.State is not AudioRecorderRuntimeState.Recording and not AudioRecorderRuntimeState.Paused) 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) private void OnUiTick(object? sender, EventArgs e)
{ {
if (!_isAttached) if (!_isAttached || !_isOnActivePage)
{ {
return; return;
} }
@@ -141,6 +156,21 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget
RefreshVisual(); RefreshVisual();
} }
private void UpdateUiTimerState()
{
if (_isAttached && _isOnActivePage)
{
if (!_uiTimer.IsEnabled)
{
_uiTimer.Start();
}
return;
}
_uiTimer.Stop();
}
private void OnDiscardButtonPointerPressed(object? sender, PointerPressedEventArgs e) private void OnDiscardButtonPointerPressed(object? sender, PointerPressedEventArgs e)
{ {
if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)

View File

@@ -16,7 +16,7 @@ using LanMountainDesktop.Services;
namespace LanMountainDesktop.Views.Components; namespace LanMountainDesktop.Views.Components;
public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget public partial class WeatherWidget : UserControl, IDesktopComponentWidget, IDesktopPageVisibilityAwareComponentWidget, ITimeZoneAwareComponentWidget, IWeatherInfoAwareComponentWidget
{ {
private enum WeatherVisualKind private enum WeatherVisualKind
{ {
@@ -93,6 +93,8 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime
private readonly List<Border> _particleVisuals = new(); private readonly List<Border> _particleVisuals = new();
private readonly List<ParticleState> _particleStates = new(); private readonly List<ParticleState> _particleStates = new();
private readonly Random _particleRandom = new(); private readonly Random _particleRandom = new();
private readonly ScaleTransform _backgroundMotionScaleTransform = new(1, 1);
private readonly TranslateTransform _backgroundMotionTranslateTransform = new();
private IWeatherInfoService _weatherInfoService = DefaultWeatherInfoService; private IWeatherInfoService _weatherInfoService = DefaultWeatherInfoService;
private TimeZoneService? _timeZoneService; private TimeZoneService? _timeZoneService;
@@ -104,11 +106,13 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime
private double _animationPhase; private double _animationPhase;
private int _activeParticleCount; private int _activeParticleCount;
private bool _isAttached; private bool _isAttached;
private bool _isOnActivePage = true;
private bool _isRefreshing; private bool _isRefreshing;
public WeatherWidget() public WeatherWidget()
{ {
InitializeComponent(); InitializeComponent();
InitializeMotionTransform();
_refreshTimer.Tick += OnRefreshTimerTick; _refreshTimer.Tick += OnRefreshTimerTick;
_backgroundAnimationTimer.Tick += OnBackgroundAnimationTick; _backgroundAnimationTimer.Tick += OnBackgroundAnimationTick;
@@ -143,7 +147,20 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
{ {
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; _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); _ = RefreshWeatherAsync(forceRefresh: false);
} }
@@ -176,16 +193,17 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = true; _isAttached = true;
_refreshTimer.Start(); UpdateTimerState();
_backgroundAnimationTimer.Start(); if (_isOnActivePage)
{
_ = RefreshWeatherAsync(forceRefresh: false); _ = RefreshWeatherAsync(forceRefresh: false);
} }
}
private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{ {
_isAttached = false; _isAttached = false;
_refreshTimer.Stop(); UpdateTimerState();
_backgroundAnimationTimer.Stop();
CancelRefreshRequest(); CancelRefreshRequest();
} }
@@ -202,7 +220,7 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime
private void OnBackgroundAnimationTick(object? sender, EventArgs e) private void OnBackgroundAnimationTick(object? sender, EventArgs e)
{ {
if (!_isAttached) if (!_isAttached || !_isOnActivePage)
{ {
return; return;
} }
@@ -265,7 +283,7 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime
private async Task RefreshWeatherAsync(bool forceRefresh) private async Task RefreshWeatherAsync(bool forceRefresh)
{ {
if (!_isAttached || _isRefreshing) if (!_isAttached || !_isOnActivePage || _isRefreshing)
{ {
return; return;
} }
@@ -980,15 +998,43 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime
private void SetMotionTransform(double translateX, double translateY, double scale) 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 Children = new Transforms
{ {
new ScaleTransform(scale, scale), _backgroundMotionScaleTransform,
new TranslateTransform(translateX, translateY) _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() private void InitializeParticleVisuals()

View File

@@ -1906,7 +1906,7 @@ public partial class MainWindow
} }
SettingsPage.IsVisible = false; SettingsPage.IsVisible = false;
}, TimeSpan.FromMilliseconds(200)); }, TimeSpan.FromMilliseconds(SettingsTransitionDurationMs));
} }
private void InitializeSettingsIcons() private void InitializeSettingsIcons()