mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 00:54:26 +08:00
0.2.8
天气组件、倒计时组件微调。引入浏览器组件。
This commit is contained in:
291
LanMontainDesktop/Views/Components/BrowserWidget.axaml.cs
Normal file
291
LanMontainDesktop/Views/Components/BrowserWidget.axaml.cs
Normal file
@@ -0,0 +1,291 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
using AvaloniaWebView;
|
||||
using WebViewCore.Events;
|
||||
|
||||
namespace LanMontainDesktop.Views.Components;
|
||||
|
||||
public partial class BrowserWidget : UserControl, IDesktopComponentWidget
|
||||
, IDesktopPageVisibilityAwareComponentWidget
|
||||
{
|
||||
private static readonly Uri DefaultHomeUri = new("https://www.bing.com");
|
||||
private double _currentCellSize = 48;
|
||||
private bool? _isNightModeApplied;
|
||||
private Uri _lastKnownUri = DefaultHomeUri;
|
||||
private bool _isOnActiveDesktopPage;
|
||||
private bool _isEditMode;
|
||||
private bool _isWebViewActive = true;
|
||||
|
||||
public BrowserWidget()
|
||||
{
|
||||
InitializeComponent();
|
||||
SizeChanged += OnSizeChanged;
|
||||
ActualThemeVariantChanged += OnActualThemeVariantChanged;
|
||||
AttachedToVisualTree += OnAttachedToVisualTree;
|
||||
DetachedFromVisualTree += OnDetachedFromVisualTree;
|
||||
|
||||
ApplyCellSize(_currentCellSize);
|
||||
ApplyTheme(force: true);
|
||||
BrowserWebView.NavigationStarting += OnBrowserWebViewNavigationStarting;
|
||||
UpdateWebViewActiveState();
|
||||
NavigateTo(DefaultHomeUri);
|
||||
}
|
||||
|
||||
public void ApplyCellSize(double cellSize)
|
||||
{
|
||||
_currentCellSize = Math.Max(1, cellSize);
|
||||
|
||||
RootBorder.CornerRadius = new CornerRadius(Math.Clamp(_currentCellSize * 0.34, 12, 28));
|
||||
RootBorder.Padding = new Thickness(
|
||||
Math.Clamp(_currentCellSize * 0.20, 8, 18));
|
||||
|
||||
WebViewHostBorder.CornerRadius = new CornerRadius(Math.Clamp(_currentCellSize * 0.24, 10, 22));
|
||||
AddressBarBorder.CornerRadius = new CornerRadius(Math.Clamp(_currentCellSize * 0.22, 10, 20));
|
||||
AddressBarBorder.Padding = new Thickness(8, 6);
|
||||
|
||||
var rowSpacing = 8d;
|
||||
if (RootBorder.Child is Grid rootGrid)
|
||||
{
|
||||
rootGrid.RowSpacing = rowSpacing;
|
||||
}
|
||||
|
||||
var buttonSize = Math.Clamp(_currentCellSize * 0.72, 30, 36);
|
||||
var buttonCorner = buttonSize * 0.5;
|
||||
var iconSize = Math.Clamp(buttonSize * 0.44, 14, 16);
|
||||
foreach (var button in new[] { RefreshButton, GoButton })
|
||||
{
|
||||
button.Width = buttonSize;
|
||||
button.Height = buttonSize;
|
||||
button.CornerRadius = new CornerRadius(buttonCorner);
|
||||
}
|
||||
|
||||
if (RefreshButton.Content is FluentIcons.Avalonia.SymbolIcon refreshIcon)
|
||||
{
|
||||
refreshIcon.FontSize = iconSize;
|
||||
}
|
||||
|
||||
if (GoButton.Content is FluentIcons.Avalonia.SymbolIcon goIcon)
|
||||
{
|
||||
goIcon.FontSize = iconSize;
|
||||
}
|
||||
|
||||
AddressTextBox.FontSize = Math.Clamp(_currentCellSize * 0.30, 12, 15);
|
||||
AddressTextBox.Height = buttonSize;
|
||||
}
|
||||
|
||||
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
ApplyTheme(force: true);
|
||||
UpdateWebViewActiveState();
|
||||
}
|
||||
|
||||
private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
_isOnActiveDesktopPage = false;
|
||||
UpdateWebViewActiveState();
|
||||
}
|
||||
|
||||
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
|
||||
{
|
||||
ApplyCellSize(_currentCellSize);
|
||||
}
|
||||
|
||||
private void OnActualThemeVariantChanged(object? sender, EventArgs e)
|
||||
{
|
||||
ApplyTheme(force: false);
|
||||
}
|
||||
|
||||
private void ApplyTheme(bool force)
|
||||
{
|
||||
var isNightMode = ResolveIsNightMode();
|
||||
if (!force && _isNightModeApplied.HasValue && _isNightModeApplied.Value == isNightMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isNightModeApplied = isNightMode;
|
||||
RootBorder.Background = new SolidColorBrush(isNightMode ? Color.Parse("#FF141A24") : Color.Parse("#FFF4F7FC"));
|
||||
WebViewHostBorder.Background = new SolidColorBrush(isNightMode ? Color.Parse("#FF0A0E15") : Color.Parse("#FFFFFFFF"));
|
||||
WebViewHostBorder.BorderBrush = new SolidColorBrush(isNightMode ? Color.Parse("#33FFFFFF") : Color.Parse("#22000000"));
|
||||
AddressBarBorder.Background = new SolidColorBrush(isNightMode ? Color.Parse("#1BFFFFFF") : Color.Parse("#ECF2FA"));
|
||||
AddressBarBorder.BorderBrush = new SolidColorBrush(isNightMode ? Color.Parse("#26FFFFFF") : Color.Parse("#22000000"));
|
||||
|
||||
var idleBackground = new SolidColorBrush(isNightMode ? Color.Parse("#24FFFFFF") : Color.Parse("#DCE6F5"));
|
||||
var idleForeground = new SolidColorBrush(isNightMode ? Color.Parse("#FFE5E7EB") : Color.Parse("#FF1E293B"));
|
||||
|
||||
foreach (var button in new[] { RefreshButton, GoButton })
|
||||
{
|
||||
button.Background = idleBackground;
|
||||
button.Foreground = idleForeground;
|
||||
button.BorderThickness = new Thickness(0);
|
||||
}
|
||||
|
||||
AddressTextBox.Background = new SolidColorBrush(isNightMode ? Color.Parse("#1F000000") : Color.Parse("#FFFFFFFF"));
|
||||
AddressTextBox.BorderBrush = new SolidColorBrush(isNightMode ? Color.Parse("#2FFFFFFF") : Color.Parse("#22000000"));
|
||||
AddressTextBox.Foreground = idleForeground;
|
||||
AddressTextBox.CaretBrush = idleForeground;
|
||||
}
|
||||
|
||||
private bool ResolveIsNightMode()
|
||||
{
|
||||
if (ActualThemeVariant == ThemeVariant.Dark)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ActualThemeVariant == ThemeVariant.Light)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.TryFindResource("AdaptiveSurfaceBaseBrush", out var value) &&
|
||||
value is ISolidColorBrush brush)
|
||||
{
|
||||
return CalculateRelativeLuminance(brush.Color) < 0.45;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static double CalculateRelativeLuminance(Color color)
|
||||
{
|
||||
static double ToLinear(double channel)
|
||||
{
|
||||
return channel <= 0.03928
|
||||
? channel / 12.92
|
||||
: Math.Pow((channel + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
var red = ToLinear(color.R / 255d);
|
||||
var green = ToLinear(color.G / 255d);
|
||||
var blue = ToLinear(color.B / 255d);
|
||||
return (0.2126 * red) + (0.7152 * green) + (0.0722 * blue);
|
||||
}
|
||||
|
||||
private void OnRefreshButtonClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isWebViewActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (BrowserWebView.Url is not null)
|
||||
{
|
||||
BrowserWebView.Reload();
|
||||
return;
|
||||
}
|
||||
|
||||
NavigateTo(DefaultHomeUri);
|
||||
}
|
||||
|
||||
private void OnGoButtonClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
NavigateFromAddressBar();
|
||||
}
|
||||
|
||||
private void OnAddressTextBoxKeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key != Key.Enter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NavigateFromAddressBar();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void NavigateFromAddressBar()
|
||||
{
|
||||
var target = TryNormalizeUri(AddressTextBox.Text);
|
||||
if (target is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NavigateTo(target);
|
||||
}
|
||||
|
||||
private void NavigateTo(Uri uri)
|
||||
{
|
||||
_lastKnownUri = uri;
|
||||
AddressTextBox.Text = uri.ToString();
|
||||
if (_isWebViewActive)
|
||||
{
|
||||
BrowserWebView.Url = uri;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBrowserWebViewNavigationStarting(object? sender, WebViewUrlLoadingEventArg e)
|
||||
{
|
||||
if (e.Url is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_lastKnownUri = e.Url;
|
||||
AddressTextBox.Text = e.Url.ToString();
|
||||
}
|
||||
|
||||
public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode)
|
||||
{
|
||||
_isOnActiveDesktopPage = isOnActivePage;
|
||||
_isEditMode = isEditMode;
|
||||
UpdateWebViewActiveState();
|
||||
}
|
||||
|
||||
private void UpdateWebViewActiveState()
|
||||
{
|
||||
var shouldBeActive = _isOnActiveDesktopPage && !_isEditMode && IsVisible;
|
||||
if (_isWebViewActive == shouldBeActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isWebViewActive = shouldBeActive;
|
||||
if (!_isWebViewActive)
|
||||
{
|
||||
if (BrowserWebView.Url is Uri currentUri)
|
||||
{
|
||||
_lastKnownUri = currentUri;
|
||||
}
|
||||
|
||||
BrowserWebView.IsHitTestVisible = false;
|
||||
BrowserWebView.IsVisible = false;
|
||||
BrowserWebView.Url = null;
|
||||
return;
|
||||
}
|
||||
|
||||
BrowserWebView.IsVisible = true;
|
||||
BrowserWebView.IsHitTestVisible = true;
|
||||
BrowserWebView.Url = _lastKnownUri;
|
||||
}
|
||||
|
||||
private static Uri? TryNormalizeUri(string? rawText)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(rawText))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var candidate = rawText.Trim();
|
||||
if (!candidate.Contains("://", StringComparison.Ordinal))
|
||||
{
|
||||
candidate = $"https://{candidate}";
|
||||
}
|
||||
|
||||
if (!Uri.TryCreate(candidate, UriKind.Absolute, out var uri))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return uri.Scheme.Equals(Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
|
||||
uri.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)
|
||||
? uri
|
||||
: null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user