mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 00:54:26 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
594a62132f | ||
|
|
15e589aedd | ||
|
|
ac4617f5cf |
@@ -510,6 +510,8 @@ public partial class App : Application
|
|||||||
|
|
||||||
if (languageChanged)
|
if (languageChanged)
|
||||||
{
|
{
|
||||||
|
// 清除本地化缓存,强制重新加载语言文件
|
||||||
|
_localizationService.ClearCache();
|
||||||
ApplyCurrentCultureFromSettings();
|
ApplyCurrentCultureFromSettings();
|
||||||
if (_trayIcons is not null)
|
if (_trayIcons is not null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -892,6 +892,6 @@
|
|||||||
"single_instance.notice.title": "应用已经运行",
|
"single_instance.notice.title": "应用已经运行",
|
||||||
"single_instance.notice.description": "应用已经运行,无需多次点击打开。",
|
"single_instance.notice.description": "应用已经运行,无需多次点击打开。",
|
||||||
"single_instance.notice.button": "确定",
|
"single_instance.notice.button": "确定",
|
||||||
"market.status.install_success_restart_format": "✓ 插件"{0}"安装成功!请重启应用以激活它。",
|
"market.status.install_success_restart_format": "✓ 插件'{0}'安装成功!请重启应用以激活它。",
|
||||||
"market.dialog.restart_message_format": "插件"{0}"已成功安装。\n\n要使用此插件,您需要立即重启应用。\n\n是否立即重启?"
|
"market.dialog.restart_message_format": "插件'{0}'已成功安装。\n\n要使用此插件,您需要立即重启应用。\n\n是否立即重启?"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,23 @@ public sealed class LocalizationService
|
|||||||
private readonly Dictionary<string, Dictionary<string, string>> _cache =
|
private readonly Dictionary<string, Dictionary<string, string>> _cache =
|
||||||
new(StringComparer.OrdinalIgnoreCase);
|
new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除指定语言代码的缓存,强制下次重新加载。
|
||||||
|
/// 在语言切换时调用此方法以确保加载最新的语言文件。
|
||||||
|
/// </summary>
|
||||||
|
public void ClearCache(string? languageCode = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(languageCode))
|
||||||
|
{
|
||||||
|
_cache.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var normalizedCode = NormalizeLanguageCode(languageCode);
|
||||||
|
_cache.Remove(normalizedCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string NormalizeLanguageCode(string? languageCode)
|
public string NormalizeLanguageCode(string? languageCode)
|
||||||
{
|
{
|
||||||
return string.Equals(languageCode, "en-US", StringComparison.OrdinalIgnoreCase)
|
return string.Equals(languageCode, "en-US", StringComparison.OrdinalIgnoreCase)
|
||||||
@@ -53,7 +70,7 @@ public sealed class LocalizationService
|
|||||||
{
|
{
|
||||||
json = json.TrimStart('\uFEFF');
|
json = json.TrimStart('\uFEFF');
|
||||||
var data = JsonSerializer.Deserialize<Dictionary<string, string>>(json, JsonOptions);
|
var data = JsonSerializer.Deserialize<Dictionary<string, string>>(json, JsonOptions);
|
||||||
if (data is not null)
|
if (data is not null && data.Count > 0)
|
||||||
{
|
{
|
||||||
result = new Dictionary<string, string>(data, StringComparer.OrdinalIgnoreCase);
|
result = new Dictionary<string, string>(data, StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
@@ -64,7 +81,11 @@ public sealed class LocalizationService
|
|||||||
// Keep empty table for resilience.
|
// Keep empty table for resilience.
|
||||||
}
|
}
|
||||||
|
|
||||||
_cache[languageCode] = result;
|
// 只有当语言表非空时才缓存,这样如果加载失败可以下次重试
|
||||||
|
if (result.Count > 0)
|
||||||
|
{
|
||||||
|
_cache[languageCode] = result;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -294,6 +294,8 @@ internal sealed class SettingsWindowService : ISettingsWindowService
|
|||||||
if (languageChanged)
|
if (languageChanged)
|
||||||
{
|
{
|
||||||
var regionState = _settingsFacade.Region.Get();
|
var regionState = _settingsFacade.Region.Get();
|
||||||
|
// 清除本地化缓存,强制重新加载语言文件
|
||||||
|
_localizationService.ClearCache();
|
||||||
_viewModel.RefreshLanguage(regionState.LanguageCode);
|
_viewModel.RefreshLanguage(regionState.LanguageCode);
|
||||||
_pageRegistry.Rebuild();
|
_pageRegistry.Rebuild();
|
||||||
_window.ReloadPages(_viewModel.CurrentPageId);
|
_window.ReloadPages(_viewModel.CurrentPageId);
|
||||||
|
|||||||
@@ -964,6 +964,7 @@ public partial class MainWindow
|
|||||||
DisposeComponentIfNeeded(host);
|
DisposeComponentIfNeeded(host);
|
||||||
contentHost.Child = component;
|
contentHost.Child = component;
|
||||||
ApplyDesktopEditStateToHost(host, _isComponentLibraryOpen);
|
ApplyDesktopEditStateToHost(host, _isComponentLibraryOpen);
|
||||||
|
InvalidateDesktopPageAwareComponentContextCache();
|
||||||
UpdateDesktopPageAwareComponentContext();
|
UpdateDesktopPageAwareComponentContext();
|
||||||
if (_selectedDesktopComponentHost == host)
|
if (_selectedDesktopComponentHost == host)
|
||||||
{
|
{
|
||||||
@@ -1102,6 +1103,7 @@ public partial class MainWindow
|
|||||||
|
|
||||||
ClearTimeZoneServiceBindings(pageGrid.Children.OfType<Control>().ToList());
|
ClearTimeZoneServiceBindings(pageGrid.Children.OfType<Control>().ToList());
|
||||||
pageGrid.Children.Clear();
|
pageGrid.Children.Clear();
|
||||||
|
InvalidateDesktopPageAwareComponentContextCache();
|
||||||
|
|
||||||
var maxColumns = pageGrid.ColumnDefinitions.Count;
|
var maxColumns = pageGrid.ColumnDefinitions.Count;
|
||||||
var maxRows = pageGrid.RowDefinitions.Count;
|
var maxRows = pageGrid.RowDefinitions.Count;
|
||||||
@@ -1204,6 +1206,7 @@ public partial class MainWindow
|
|||||||
pageGrid.Children.Add(host);
|
pageGrid.Children.Add(host);
|
||||||
|
|
||||||
_desktopComponentPlacements.Add(placement);
|
_desktopComponentPlacements.Add(placement);
|
||||||
|
InvalidateDesktopPageAwareComponentContextCache();
|
||||||
UpdateDesktopPageAwareComponentContext();
|
UpdateDesktopPageAwareComponentContext();
|
||||||
PersistSettings();
|
PersistSettings();
|
||||||
|
|
||||||
@@ -1577,14 +1580,86 @@ public partial class MainWindow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InvalidateDesktopPageAwareComponentContextCache()
|
||||||
|
{
|
||||||
|
_desktopPageContextInitialized = false;
|
||||||
|
_desktopPageContextActiveMask = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int BuildDesktopPageAwareComponentActiveMask()
|
||||||
|
{
|
||||||
|
if (_isSettingsOpen)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var activeMask = 0;
|
||||||
|
if (_desktopSurfacePageWidth > 1 &&
|
||||||
|
_desktopPagesHostTransform is not null &&
|
||||||
|
(_isDesktopSwipeActive ||
|
||||||
|
_desktopPageContextSettlingSourceIndex is not null ||
|
||||||
|
_desktopPageContextSettlingTargetIndex is not null))
|
||||||
|
{
|
||||||
|
var viewportLeft = -_desktopPagesHostTransform.X;
|
||||||
|
var viewportRight = viewportLeft + _desktopSurfacePageWidth;
|
||||||
|
for (var pageIndex = 0; pageIndex < _desktopPageCount; pageIndex++)
|
||||||
|
{
|
||||||
|
var pageLeft = pageIndex * _desktopSurfacePageWidth;
|
||||||
|
var pageRight = pageLeft + _desktopSurfacePageWidth;
|
||||||
|
if (pageRight > viewportLeft + 0.5d && pageLeft < viewportRight - 0.5d)
|
||||||
|
{
|
||||||
|
activeMask |= 1 << pageIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_currentDesktopSurfaceIndex >= 0 && _currentDesktopSurfaceIndex < _desktopPageCount)
|
||||||
|
{
|
||||||
|
activeMask |= 1 << _currentDesktopSurfaceIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_desktopPageContextSettlingSourceIndex is int sourceIndex &&
|
||||||
|
sourceIndex >= 0 &&
|
||||||
|
sourceIndex < _desktopPageCount)
|
||||||
|
{
|
||||||
|
activeMask |= 1 << sourceIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_desktopPageContextSettlingTargetIndex is int targetIndex &&
|
||||||
|
targetIndex >= 0 &&
|
||||||
|
targetIndex < _desktopPageCount)
|
||||||
|
{
|
||||||
|
activeMask |= 1 << targetIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeMask;
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateDesktopPageAwareComponentContext()
|
private void UpdateDesktopPageAwareComponentContext()
|
||||||
{
|
{
|
||||||
var activeDesktopPageIndex = _isSettingsOpen ? -1 : _currentDesktopSurfaceIndex;
|
|
||||||
var isEditMode = _isComponentLibraryOpen || _isSettingsOpen;
|
var isEditMode = _isComponentLibraryOpen || _isSettingsOpen;
|
||||||
|
var activeMask = BuildDesktopPageAwareComponentActiveMask();
|
||||||
|
var pageUpdateMask = !_desktopPageContextInitialized || isEditMode != _desktopPageContextEditMode
|
||||||
|
? _desktopPageComponentGrids.Keys.Aggregate(0, (mask, pageIndex) => mask | (1 << pageIndex))
|
||||||
|
: activeMask ^ _desktopPageContextActiveMask;
|
||||||
|
|
||||||
|
if (_desktopPageContextInitialized &&
|
||||||
|
pageUpdateMask == 0 &&
|
||||||
|
isEditMode == _desktopPageContextEditMode &&
|
||||||
|
activeMask == _desktopPageContextActiveMask)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var pair in _desktopPageComponentGrids)
|
foreach (var pair in _desktopPageComponentGrids)
|
||||||
{
|
{
|
||||||
var isOnActivePage = pair.Key == activeDesktopPageIndex;
|
var pageBit = 1 << pair.Key;
|
||||||
|
if ((pageUpdateMask & pageBit) == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isOnActivePage = (activeMask & pageBit) != 0;
|
||||||
foreach (var host in pair.Value.Children.OfType<Border>())
|
foreach (var host in pair.Value.Children.OfType<Border>())
|
||||||
{
|
{
|
||||||
if (!host.Classes.Contains(DesktopComponentHostClass))
|
if (!host.Classes.Contains(DesktopComponentHostClass))
|
||||||
@@ -1598,6 +1673,10 @@ public partial class MainWindow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_desktopPageContextInitialized = true;
|
||||||
|
_desktopPageContextEditMode = isEditMode;
|
||||||
|
_desktopPageContextActiveMask = activeMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ApplyDesktopPageContext(Control root, bool isOnActivePage, bool isEditMode)
|
private static void ApplyDesktopPageContext(Control root, bool isOnActivePage, bool isEditMode)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
using Avalonia.Animation;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
@@ -16,6 +17,7 @@ using Avalonia.VisualTree;
|
|||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using LanMountainDesktop.Models;
|
using LanMountainDesktop.Models;
|
||||||
using LanMountainDesktop.Services;
|
using LanMountainDesktop.Services;
|
||||||
|
using LanMountainDesktop.Theme;
|
||||||
|
|
||||||
namespace LanMountainDesktop.Views;
|
namespace LanMountainDesktop.Views;
|
||||||
|
|
||||||
@@ -54,6 +56,8 @@ public partial class MainWindow
|
|||||||
private int _currentDesktopSurfaceIndex;
|
private int _currentDesktopSurfaceIndex;
|
||||||
private double _desktopSurfacePageWidth;
|
private double _desktopSurfacePageWidth;
|
||||||
private TranslateTransform? _desktopPagesHostTransform;
|
private TranslateTransform? _desktopPagesHostTransform;
|
||||||
|
private Transitions? _desktopPagesHostSnapTransitions;
|
||||||
|
private bool _desktopPagesHostTransitionsSuspended;
|
||||||
private bool _isDesktopSwipeActive;
|
private bool _isDesktopSwipeActive;
|
||||||
private bool _isDesktopSwipeDirectionLocked;
|
private bool _isDesktopSwipeDirectionLocked;
|
||||||
private Point _desktopSwipeStartPoint;
|
private Point _desktopSwipeStartPoint;
|
||||||
@@ -62,6 +66,12 @@ public partial class MainWindow
|
|||||||
private long _desktopSwipeLastTimestamp;
|
private long _desktopSwipeLastTimestamp;
|
||||||
private double _desktopSwipeVelocityX;
|
private double _desktopSwipeVelocityX;
|
||||||
private double _desktopSwipeBaseOffset;
|
private double _desktopSwipeBaseOffset;
|
||||||
|
private bool _desktopPageContextInitialized;
|
||||||
|
private bool _desktopPageContextEditMode;
|
||||||
|
private int _desktopPageContextActiveMask;
|
||||||
|
private int? _desktopPageContextSettlingSourceIndex;
|
||||||
|
private int? _desktopPageContextSettlingTargetIndex;
|
||||||
|
private int _desktopPageContextSettleRevision;
|
||||||
|
|
||||||
private int LauncherSurfaceIndex => Math.Max(MinDesktopPageCount, _desktopPageCount);
|
private int LauncherSurfaceIndex => Math.Max(MinDesktopPageCount, _desktopPageCount);
|
||||||
|
|
||||||
@@ -164,6 +174,15 @@ public partial class MainWindow
|
|||||||
DesktopPagesHost.RenderTransform = _desktopPagesHostTransform;
|
DesktopPagesHost.RenderTransform = _desktopPagesHostTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_desktopPagesHostTransitionsSuspended)
|
||||||
|
{
|
||||||
|
_desktopPagesHostTransform.Transitions = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_desktopPagesHostSnapTransitions ??= _desktopPagesHostTransform.Transitions;
|
||||||
|
}
|
||||||
|
|
||||||
var viewportRow = gridMetrics.RowCount > 2 ? 1 : 0;
|
var viewportRow = gridMetrics.RowCount > 2 ? 1 : 0;
|
||||||
var viewportRowSpan = gridMetrics.RowCount > 2 ? gridMetrics.RowCount - 2 : 1;
|
var viewportRowSpan = gridMetrics.RowCount > 2 ? gridMetrics.RowCount - 2 : 1;
|
||||||
var pageWidth = Math.Max(1, gridMetrics.GridWidthPx);
|
var pageWidth = Math.Max(1, gridMetrics.GridWidthPx);
|
||||||
@@ -200,6 +219,7 @@ public partial class MainWindow
|
|||||||
DesktopPagesContainer.Width = pageWidth * _desktopPageCount;
|
DesktopPagesContainer.Width = pageWidth * _desktopPageCount;
|
||||||
DesktopPagesContainer.Height = pageHeight;
|
DesktopPagesContainer.Height = pageHeight;
|
||||||
_desktopPageComponentGrids.Clear();
|
_desktopPageComponentGrids.Clear();
|
||||||
|
InvalidateDesktopPageAwareComponentContextCache();
|
||||||
for (var index = 0; index < _desktopPageCount; index++)
|
for (var index = 0; index < _desktopPageCount; index++)
|
||||||
{
|
{
|
||||||
DesktopPagesContainer.ColumnDefinitions.Add(new ColumnDefinition(new GridLength(pageWidth, GridUnitType.Pixel)));
|
DesktopPagesContainer.ColumnDefinitions.Add(new ColumnDefinition(new GridLength(pageWidth, GridUnitType.Pixel)));
|
||||||
@@ -354,6 +374,88 @@ public partial class MainWindow
|
|||||||
UpdateDesktopPageAwareComponentContext();
|
UpdateDesktopPageAwareComponentContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetDesktopPagesHostSnapAnimationEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
if (_desktopPagesHostTransform is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
if (!_desktopPagesHostTransitionsSuspended)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_desktopPagesHostTransform.Transitions = _desktopPagesHostSnapTransitions;
|
||||||
|
_desktopPagesHostTransitionsSuspended = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_desktopPagesHostTransitionsSuspended)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_desktopPagesHostSnapTransitions ??= _desktopPagesHostTransform.Transitions;
|
||||||
|
_desktopPagesHostTransform.Transitions = null;
|
||||||
|
_desktopPagesHostTransitionsSuspended = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearDesktopPageContextSettle(bool refreshContext)
|
||||||
|
{
|
||||||
|
_desktopPageContextSettleRevision++;
|
||||||
|
_desktopPageContextSettlingSourceIndex = null;
|
||||||
|
_desktopPageContextSettlingTargetIndex = null;
|
||||||
|
|
||||||
|
if (refreshContext)
|
||||||
|
{
|
||||||
|
UpdateDesktopPageAwareComponentContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginDesktopPageContextSettle(int previousIndex, int targetIndex)
|
||||||
|
{
|
||||||
|
var sourceIndex = previousIndex >= 0 && previousIndex < _desktopPageCount
|
||||||
|
? previousIndex
|
||||||
|
: (int?)null;
|
||||||
|
var destinationIndex = targetIndex >= 0 && targetIndex < _desktopPageCount
|
||||||
|
? targetIndex
|
||||||
|
: (int?)null;
|
||||||
|
|
||||||
|
if (sourceIndex == destinationIndex && destinationIndex is not null)
|
||||||
|
{
|
||||||
|
ClearDesktopPageContextSettle(refreshContext: false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceIndex is null && destinationIndex is null)
|
||||||
|
{
|
||||||
|
ClearDesktopPageContextSettle(refreshContext: false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_desktopPageContextSettleRevision++;
|
||||||
|
var settleRevision = _desktopPageContextSettleRevision;
|
||||||
|
_desktopPageContextSettlingSourceIndex = sourceIndex;
|
||||||
|
_desktopPageContextSettlingTargetIndex = destinationIndex;
|
||||||
|
|
||||||
|
DispatcherTimer.RunOnce(
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if (settleRevision != _desktopPageContextSettleRevision)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_desktopPageContextSettlingSourceIndex = null;
|
||||||
|
_desktopPageContextSettlingTargetIndex = null;
|
||||||
|
UpdateDesktopPageAwareComponentContext();
|
||||||
|
},
|
||||||
|
FluttermotionToken.Page + TimeSpan.FromMilliseconds(36));
|
||||||
|
}
|
||||||
|
|
||||||
private void MoveSurfaceBy(int delta)
|
private void MoveSurfaceBy(int delta)
|
||||||
{
|
{
|
||||||
if (delta == 0)
|
if (delta == 0)
|
||||||
@@ -373,9 +475,11 @@ public partial class MainWindow
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var previousIndex = _currentDesktopSurfaceIndex;
|
||||||
_currentDesktopSurfaceIndex = target;
|
_currentDesktopSurfaceIndex = target;
|
||||||
|
BeginDesktopPageContextSettle(previousIndex, target);
|
||||||
ApplyDesktopSurfaceOffset();
|
ApplyDesktopSurfaceOffset();
|
||||||
PersistSettings();
|
SchedulePersistSettings(delayMs: Math.Max(280, (int)FluttermotionToken.Page.TotalMilliseconds + 80));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanSwipeDesktopSurface()
|
private bool CanSwipeDesktopSurface()
|
||||||
@@ -426,6 +530,7 @@ public partial class MainWindow
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClearDesktopPageContextSettle(refreshContext: false);
|
||||||
_isDesktopSwipeActive = true;
|
_isDesktopSwipeActive = true;
|
||||||
_isDesktopSwipeDirectionLocked = false;
|
_isDesktopSwipeDirectionLocked = false;
|
||||||
_desktopSwipeStartPoint = pointerInViewport;
|
_desktopSwipeStartPoint = pointerInViewport;
|
||||||
@@ -603,6 +708,7 @@ public partial class MainWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
_isDesktopSwipeDirectionLocked = true;
|
_isDesktopSwipeDirectionLocked = true;
|
||||||
|
SetDesktopPagesHostSnapAnimationEnabled(enabled: false);
|
||||||
if (e.Pointer.Captured != DesktopPagesViewport)
|
if (e.Pointer.Captured != DesktopPagesViewport)
|
||||||
{
|
{
|
||||||
e.Pointer.Capture(DesktopPagesViewport);
|
e.Pointer.Capture(DesktopPagesViewport);
|
||||||
@@ -621,6 +727,7 @@ public partial class MainWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
_desktopPagesHostTransform.X = tentative;
|
_desktopPagesHostTransform.X = tentative;
|
||||||
|
UpdateDesktopPageAwareComponentContext();
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,6 +763,7 @@ public partial class MainWindow
|
|||||||
_desktopSwipeLastTimestamp = 0;
|
_desktopSwipeLastTimestamp = 0;
|
||||||
if (wasDirectionLocked)
|
if (wasDirectionLocked)
|
||||||
{
|
{
|
||||||
|
SetDesktopPagesHostSnapAnimationEnabled(enabled: true);
|
||||||
ApplyDesktopSurfaceOffset();
|
ApplyDesktopSurfaceOffset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -682,6 +790,8 @@ public partial class MainWindow
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetDesktopPagesHostSnapAnimationEnabled(enabled: true);
|
||||||
|
|
||||||
var deltaX = _desktopSwipeCurrentPoint.X - _desktopSwipeStartPoint.X;
|
var deltaX = _desktopSwipeCurrentPoint.X - _desktopSwipeStartPoint.X;
|
||||||
var deltaY = _desktopSwipeCurrentPoint.Y - _desktopSwipeStartPoint.Y;
|
var deltaY = _desktopSwipeCurrentPoint.Y - _desktopSwipeStartPoint.Y;
|
||||||
var absDeltaX = Math.Abs(deltaX);
|
var absDeltaX = Math.Abs(deltaX);
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ public partial class MainWindow
|
|||||||
{
|
{
|
||||||
_ = sender;
|
_ = sender;
|
||||||
|
|
||||||
|
if (_suppressOwnSettingsReloadCount > 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.Scope == SettingsScope.App && e.ChangedKeys is { Count: > 0 })
|
if (e.Scope == SettingsScope.App && e.ChangedKeys is { Count: > 0 })
|
||||||
{
|
{
|
||||||
var changedKeys = e.ChangedKeys.ToArray();
|
var changedKeys = e.ChangedKeys.ToArray();
|
||||||
@@ -382,6 +387,7 @@ public partial class MainWindow
|
|||||||
|
|
||||||
private void PersistSettings()
|
private void PersistSettings()
|
||||||
{
|
{
|
||||||
|
_persistSettingsRevision++;
|
||||||
if (_suppressSettingsPersistence)
|
if (_suppressSettingsPersistence)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -389,6 +395,8 @@ public partial class MainWindow
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Saving our own state should not trigger a full external reload cycle.
|
||||||
|
_suppressOwnSettingsReloadCount++;
|
||||||
_settingsService.SaveSnapshot(SettingsScope.App, BuildAppSettingsSnapshot());
|
_settingsService.SaveSnapshot(SettingsScope.App, BuildAppSettingsSnapshot());
|
||||||
_componentLayoutStore.SaveLayout(BuildDesktopLayoutSettingsSnapshot());
|
_componentLayoutStore.SaveLayout(BuildDesktopLayoutSettingsSnapshot());
|
||||||
_settingsService.SaveSnapshot(SettingsScope.Launcher, BuildLauncherSettingsSnapshot());
|
_settingsService.SaveSnapshot(SettingsScope.Launcher, BuildLauncherSettingsSnapshot());
|
||||||
@@ -397,11 +405,29 @@ public partial class MainWindow
|
|||||||
{
|
{
|
||||||
AppLogger.Warn("SettingsRuntime", "Failed to persist settings.", ex);
|
AppLogger.Warn("SettingsRuntime", "Failed to persist settings.", ex);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (_suppressOwnSettingsReloadCount > 0)
|
||||||
|
{
|
||||||
|
_suppressOwnSettingsReloadCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SchedulePersistSettings(int delayMs = 200)
|
private void SchedulePersistSettings(int delayMs = 200)
|
||||||
{
|
{
|
||||||
DispatcherTimer.RunOnce(PersistSettings, TimeSpan.FromMilliseconds(Math.Max(0, delayMs)));
|
var revision = ++_persistSettingsRevision;
|
||||||
|
DispatcherTimer.RunOnce(
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if (revision != _persistSettingsRevision)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PersistSettings();
|
||||||
|
},
|
||||||
|
TimeSpan.FromMilliseconds(Math.Max(0, delayMs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ReloadFromPersistedSettings()
|
internal void ReloadFromPersistedSettings()
|
||||||
|
|||||||
@@ -145,7 +145,9 @@
|
|||||||
<TranslateTransform>
|
<TranslateTransform>
|
||||||
<TranslateTransform.Transitions>
|
<TranslateTransform.Transitions>
|
||||||
<Transitions>
|
<Transitions>
|
||||||
<DoubleTransition Property="X" Duration="{StaticResource FluttermotionToken.Duration.Page}" />
|
<DoubleTransition Property="X"
|
||||||
|
Duration="{StaticResource FluttermotionToken.Duration.Page}"
|
||||||
|
Easing="0.22,1,0.36,1" />
|
||||||
</Transitions>
|
</Transitions>
|
||||||
</TranslateTransform.Transitions>
|
</TranslateTransform.Transitions>
|
||||||
</TranslateTransform>
|
</TranslateTransform>
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ public partial class MainWindow : Window, ISettingsWindowAnchorProvider
|
|||||||
private bool _isWeatherPreviewInProgress;
|
private bool _isWeatherPreviewInProgress;
|
||||||
private ClockDisplayFormat _clockDisplayFormat = ClockDisplayFormat.HourMinuteSecond;
|
private ClockDisplayFormat _clockDisplayFormat = ClockDisplayFormat.HourMinuteSecond;
|
||||||
private bool _externalSettingsReloadPending;
|
private bool _externalSettingsReloadPending;
|
||||||
|
private int _persistSettingsRevision;
|
||||||
|
private int _suppressOwnSettingsReloadCount;
|
||||||
private double CurrentDesktopPitch => _currentDesktopCellSize + _currentDesktopCellGap;
|
private double CurrentDesktopPitch => _currentDesktopCellSize + _currentDesktopCellGap;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
|
|||||||
@@ -70,9 +70,11 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid ColumnDefinitions="Auto,*"
|
<Grid ColumnDefinitions="Auto,*"
|
||||||
|
RowDefinitions="Auto,Auto"
|
||||||
ColumnSpacing="20"
|
ColumnSpacing="20"
|
||||||
RowSpacing="16">
|
RowSpacing="16">
|
||||||
<StackPanel Grid.Column="0"
|
<StackPanel Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
Spacing="4">
|
Spacing="4">
|
||||||
<TextBlock Classes="update-kv-label"
|
<TextBlock Classes="update-kv-label"
|
||||||
Text="{Binding CurrentVersionLabel}" />
|
Text="{Binding CurrentVersionLabel}" />
|
||||||
@@ -80,7 +82,8 @@
|
|||||||
Text="{Binding CurrentVersionText}" />
|
Text="{Binding CurrentVersionText}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Grid.Column="1"
|
<StackPanel Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
Spacing="4"
|
Spacing="4"
|
||||||
IsVisible="{Binding IsLatestVersionVisible}">
|
IsVisible="{Binding IsLatestVersionVisible}">
|
||||||
<TextBlock Classes="update-kv-label"
|
<TextBlock Classes="update-kv-label"
|
||||||
@@ -110,22 +113,26 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<StackPanel Spacing="12">
|
<StackPanel Spacing="12"
|
||||||
|
HorizontalAlignment="Left">
|
||||||
<TextBlock Classes="settings-item-description"
|
<TextBlock Classes="settings-item-description"
|
||||||
Text="{Binding UpdateStatus}"
|
Text="{Binding UpdateStatus}"
|
||||||
TextWrapping="Wrap"
|
TextWrapping="Wrap"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
MaxWidth="500" />
|
MaxWidth="500" />
|
||||||
|
|
||||||
<ProgressBar Minimum="0"
|
<ProgressBar Minimum="0"
|
||||||
Maximum="100"
|
Maximum="100"
|
||||||
Value="{Binding DownloadProgressValue}"
|
Value="{Binding DownloadProgressValue}"
|
||||||
IsVisible="{Binding IsDownloadProgressVisible}"
|
IsVisible="{Binding IsDownloadProgressVisible}"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
Margin="0,4,0,4" />
|
Margin="0,4,0,4" />
|
||||||
|
|
||||||
<TextBlock Classes="settings-item-description"
|
<TextBlock Classes="settings-item-description"
|
||||||
IsVisible="{Binding IsDownloadProgressVisible}"
|
IsVisible="{Binding IsDownloadProgressVisible}"
|
||||||
Text="{Binding DownloadProgressText}"
|
Text="{Binding DownloadProgressText}"
|
||||||
TextWrapping="Wrap"
|
TextWrapping="Wrap"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
Margin="0,4,0,0" />
|
Margin="0,4,0,0" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user