403 lines
16 KiB
C#
403 lines
16 KiB
C#
using Microsoft.UI.Text;
|
|
using Microsoft.UI.Xaml;
|
|
using Microsoft.UI.Xaml.Automation;
|
|
using Microsoft.UI.Xaml.Controls;
|
|
using Microsoft.UI.Xaml.Media;
|
|
using Windows.UI.Text;
|
|
using YMhut.Box.Core.Updates;
|
|
using YMhut.Box.WinUI.Services;
|
|
|
|
namespace YMhut.Box.WinUI.Controls;
|
|
|
|
internal sealed class AppShell : Grid
|
|
{
|
|
private readonly Dictionary<string, NavigationViewItem> _routeItems = new(StringComparer.OrdinalIgnoreCase);
|
|
|
|
public AppShell(
|
|
IAppVersionService versionService,
|
|
ITitleWeatherService titleWeatherService,
|
|
IReadOnlyList<ShellRoute> routes)
|
|
{
|
|
Background = ModernUi.AppBackground;
|
|
RowDefinitions.Add(new RowDefinition { Height = new GridLength(48) });
|
|
RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
|
|
|
|
TitleBar = new AppTitleBar(versionService.GetCurrent().Version, titleWeatherService);
|
|
Grid.SetRow(TitleBar, 0);
|
|
Children.Add(TitleBar);
|
|
|
|
RootNavigation = BuildNavigation(routes);
|
|
Grid.SetRow(RootNavigation, 1);
|
|
Children.Add(RootNavigation);
|
|
|
|
QuickSettingsOverlay = BuildQuickSettingsOverlay();
|
|
Grid.SetRowSpan(QuickSettingsOverlay, 2);
|
|
Children.Add(QuickSettingsOverlay);
|
|
|
|
ToastPresenter = new StackPanel
|
|
{
|
|
HorizontalAlignment = HorizontalAlignment.Right,
|
|
VerticalAlignment = VerticalAlignment.Bottom,
|
|
Margin = new Thickness(0, 0, 28, 28),
|
|
Spacing = 10,
|
|
IsHitTestVisible = false
|
|
};
|
|
Grid.SetRowSpan(ToastPresenter, 2);
|
|
Children.Add(ToastPresenter);
|
|
}
|
|
|
|
public AppTitleBar TitleBar { get; }
|
|
|
|
public NavigationView RootNavigation { get; }
|
|
|
|
public BreadcrumbBar BreadcrumbBar { get; private set; } = null!;
|
|
|
|
public ContentControl ContentHost { get; private set; } = null!;
|
|
|
|
public Grid QuickSettingsOverlay { get; private set; } = null!;
|
|
|
|
public Border QuickSettingsScrim { get; private set; } = null!;
|
|
|
|
public Border QuickSettingsPanel { get; private set; } = null!;
|
|
|
|
public TranslateTransform QuickSettingsTransform { get; private set; } = null!;
|
|
|
|
public StackPanel ToastPresenter { get; }
|
|
|
|
public Button CloseQuickSettingsButton { get; private set; } = null!;
|
|
|
|
public Button QuickLightButton { get; private set; } = null!;
|
|
|
|
public Button QuickDarkButton { get; private set; } = null!;
|
|
|
|
public Button QuickFontSmallButton { get; private set; } = null!;
|
|
|
|
public Button QuickFontNormalButton { get; private set; } = null!;
|
|
|
|
public Button QuickFontLargeButton { get; private set; } = null!;
|
|
|
|
public ToggleSwitch QuickAnimationSwitch { get; private set; } = null!;
|
|
|
|
public ToggleSwitch QuickProxySwitch { get; private set; } = null!;
|
|
|
|
public ToggleSwitch QuickUpdateSwitch { get; private set; } = null!;
|
|
|
|
public ToggleSwitch QuickHardwareAccelerationSwitch { get; private set; } = null!;
|
|
|
|
public ToggleSwitch QuickPluginSwitch { get; private set; } = null!;
|
|
|
|
public Button QuickLanguageZhButton { get; private set; } = null!;
|
|
|
|
public Button QuickLanguageEnButton { get; private set; } = null!;
|
|
|
|
public Button QuickHomeSolarButton { get; private set; } = null!;
|
|
|
|
public Button QuickHomeDashboardButton { get; private set; } = null!;
|
|
|
|
public Button QuickBackdropMicaButton { get; private set; } = null!;
|
|
|
|
public Button QuickBackdropAcrylicButton { get; private set; } = null!;
|
|
|
|
public Button QuickBackdropSolidButton { get; private set; } = null!;
|
|
|
|
public Button QuickTopInheritButton { get; private set; } = null!;
|
|
|
|
public Button QuickTopAcrylicButton { get; private set; } = null!;
|
|
|
|
public Button QuickTopSolidButton { get; private set; } = null!;
|
|
|
|
public Button QuickContentSolidButton { get; private set; } = null!;
|
|
|
|
public Button QuickContentAcrylicButton { get; private set; } = null!;
|
|
|
|
public Button QuickContentGlassButton { get; private set; } = null!;
|
|
|
|
public Button QuickCloseAskButton { get; private set; } = null!;
|
|
|
|
public Button QuickCloseMinimizeButton { get; private set; } = null!;
|
|
|
|
public Button QuickCloseExitButton { get; private set; } = null!;
|
|
|
|
public Button QuickOpenSettingsButton { get; private set; } = null!;
|
|
|
|
public NavigationViewItem GetRequiredItem(string tag)
|
|
{
|
|
return _routeItems[tag];
|
|
}
|
|
|
|
public void SetBreadcrumbs(IReadOnlyList<string> breadcrumbs)
|
|
{
|
|
BreadcrumbBar.ItemsSource = breadcrumbs.Count > 0
|
|
? breadcrumbs
|
|
: [AppLocalizer.T("首页", "Home")];
|
|
}
|
|
|
|
private NavigationView BuildNavigation(IReadOnlyList<ShellRoute> routes)
|
|
{
|
|
var navigation = new NavigationView
|
|
{
|
|
IsBackButtonVisible = NavigationViewBackButtonVisible.Collapsed,
|
|
IsSettingsVisible = false,
|
|
PaneDisplayMode = NavigationViewPaneDisplayMode.LeftCompact,
|
|
IsPaneOpen = false,
|
|
CompactPaneLength = 56,
|
|
OpenPaneLength = 260,
|
|
SelectionFollowsFocus = NavigationViewSelectionFollowsFocus.Disabled,
|
|
Background = ModernUi.Brush("#00FFFFFF"),
|
|
PaneTitle = "YMhut Box",
|
|
AutoSuggestBox = TitleBar.GlobalSearchBox
|
|
};
|
|
|
|
BreadcrumbBar = new BreadcrumbBar
|
|
{
|
|
Margin = new Thickness(24, 8, 24, 6),
|
|
FontSize = 16,
|
|
FontWeight = Microsoft.UI.Text.FontWeights.SemiBold,
|
|
Visibility = Visibility.Collapsed,
|
|
ItemsSource = new[] { AppLocalizer.T("首页", "Home") }
|
|
};
|
|
|
|
foreach (var route in routes.Where(route => route.Placement is ShellRoutePlacement.Main))
|
|
{
|
|
navigation.MenuItems.Add(CreateNavigationItem(route));
|
|
}
|
|
|
|
foreach (var route in routes.Where(route => route.Placement is ShellRoutePlacement.Footer))
|
|
{
|
|
navigation.FooterMenuItems.Add(CreateNavigationItem(route));
|
|
}
|
|
|
|
ContentHost = new ContentControl
|
|
{
|
|
IsTabStop = true,
|
|
HorizontalContentAlignment = HorizontalAlignment.Stretch,
|
|
VerticalContentAlignment = VerticalAlignment.Stretch,
|
|
HorizontalAlignment = HorizontalAlignment.Stretch,
|
|
VerticalAlignment = VerticalAlignment.Stretch,
|
|
Margin = new Thickness(0, 0, 0, 0)
|
|
};
|
|
navigation.Content = ContentHost;
|
|
return navigation;
|
|
}
|
|
|
|
private NavigationViewItem CreateNavigationItem(ShellRoute route)
|
|
{
|
|
var item = new NavigationViewItem
|
|
{
|
|
Content = route.CurrentTitle,
|
|
Tag = route.Tag,
|
|
Icon = new FontIcon { Glyph = route.IconGlyph },
|
|
UseSystemFocusVisuals = true
|
|
};
|
|
ToolTipService.SetToolTip(item, route.CurrentTitle);
|
|
AutomationProperties.SetName(item, route.CurrentTitle);
|
|
_routeItems[route.Tag] = item;
|
|
return item;
|
|
}
|
|
|
|
private Grid BuildQuickSettingsOverlay()
|
|
{
|
|
QuickSettingsScrim = new Border { Background = ModernUi.Brush("#55000000") };
|
|
QuickSettingsTransform = new TranslateTransform { X = 392 };
|
|
CloseQuickSettingsButton = CreateIconButton("\uE711", AppLocalizer.T("关闭快速设置", "Close quick settings"));
|
|
CloseQuickSettingsButton.Width = 38;
|
|
QuickLightButton = QuickOptionButton("浅色", "Light");
|
|
QuickDarkButton = QuickOptionButton("深色", "Dark");
|
|
QuickLanguageZhButton = QuickOptionButton("中文", "Chinese");
|
|
QuickLanguageEnButton = QuickOptionButton("English", "English");
|
|
QuickHomeSolarButton = QuickOptionButton("太阳系", "Solar");
|
|
QuickHomeDashboardButton = QuickOptionButton("仪表盘", "Dashboard");
|
|
QuickBackdropMicaButton = QuickOptionButton("云母", "Mica");
|
|
QuickBackdropAcrylicButton = QuickOptionButton("亚克力", "Acrylic");
|
|
QuickBackdropSolidButton = QuickOptionButton("纯色", "Solid");
|
|
QuickTopInheritButton = QuickOptionButton("继承", "Inherit");
|
|
QuickTopAcrylicButton = QuickOptionButton("亚克力", "Acrylic");
|
|
QuickTopSolidButton = QuickOptionButton("纯色", "Solid");
|
|
QuickContentSolidButton = QuickOptionButton("纯色", "Solid");
|
|
QuickContentAcrylicButton = QuickOptionButton("亚克力", "Acrylic");
|
|
QuickContentGlassButton = QuickOptionButton("毛玻璃", "Glass");
|
|
QuickCloseAskButton = QuickOptionButton("询问", "Ask");
|
|
QuickCloseMinimizeButton = QuickOptionButton("托盘", "Tray");
|
|
QuickCloseExitButton = QuickOptionButton("退出", "Exit");
|
|
QuickAnimationSwitch = QuickSwitch("界面动画", "Animations");
|
|
QuickProxySwitch = QuickSwitch("启用代理", "Use proxy");
|
|
QuickUpdateSwitch = QuickSwitch("更新提醒", "Update reminders");
|
|
QuickHardwareAccelerationSwitch = QuickSwitch("硬件加速", "Hardware acceleration");
|
|
QuickPluginSwitch = QuickSwitch("插件系统", "Plugin system");
|
|
QuickFontSmallButton = QuickOptionButton("小", "Small");
|
|
QuickFontNormalButton = QuickOptionButton("标准", "Normal");
|
|
QuickFontLargeButton = QuickOptionButton("大", "Large");
|
|
QuickOpenSettingsButton = ModernUi.PillButton(AppLocalizer.T("打开完整设置", "Open full settings"), "\uE713", null, primary: true);
|
|
QuickOpenSettingsButton.Tag = new LocalizedText("打开完整设置", "Open full settings");
|
|
QuickOpenSettingsButton.HorizontalAlignment = HorizontalAlignment.Stretch;
|
|
|
|
var header = new Grid();
|
|
header.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
|
header.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
|
header.Children.Add(new StackPanel
|
|
{
|
|
Spacing = 4,
|
|
Children =
|
|
{
|
|
QuickText("快速设置", "Quick settings", 24, FontWeights.SemiBold),
|
|
QuickText("常用显示、行为和运行选项集中在这里。", "Common display, behavior, and runtime options live here.", 13, foreground: ModernUi.TextSecondary)
|
|
}
|
|
});
|
|
Grid.SetColumn(CloseQuickSettingsButton, 1);
|
|
header.Children.Add(CloseQuickSettingsButton);
|
|
|
|
QuickSettingsPanel = new Border
|
|
{
|
|
Width = 392,
|
|
HorizontalAlignment = HorizontalAlignment.Right,
|
|
Background = ModernUi.SidebarBackground,
|
|
BorderBrush = ModernUi.Stroke,
|
|
BorderThickness = new Thickness(1, 0, 0, 0),
|
|
RenderTransform = QuickSettingsTransform,
|
|
Child = new ScrollViewer
|
|
{
|
|
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
|
|
HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled,
|
|
Padding = new Thickness(0, 0, 8, 0),
|
|
Content = new StackPanel
|
|
{
|
|
Padding = new Thickness(22, 24, 14, 22),
|
|
Spacing = 16,
|
|
Children =
|
|
{
|
|
header,
|
|
QuickSettingsCard("外观", "Appearance", "\uE706",
|
|
QuickLabel("主题", "Theme"),
|
|
QuickColumns(QuickLightButton, QuickDarkButton),
|
|
QuickLabel("窗口材质", "Window material"),
|
|
QuickColumns(QuickBackdropMicaButton, QuickBackdropAcrylicButton, QuickBackdropSolidButton),
|
|
QuickLabel("顶部材质", "Top bar material"),
|
|
QuickColumns(QuickTopInheritButton, QuickTopAcrylicButton, QuickTopSolidButton),
|
|
QuickLabel("内容材质", "Content material"),
|
|
QuickColumns(QuickContentSolidButton, QuickContentAcrylicButton, QuickContentGlassButton),
|
|
QuickLabel("字体缩放", "Font scale"),
|
|
QuickColumns(QuickFontSmallButton, QuickFontNormalButton, QuickFontLargeButton),
|
|
QuickAnimationSwitch),
|
|
QuickSettingsCard("页面与输入", "Pages and input", "\uE80F",
|
|
QuickLabel("首页内容", "Home content"),
|
|
QuickColumns(QuickHomeSolarButton, QuickHomeDashboardButton),
|
|
QuickLabel("语言", "Language"),
|
|
QuickColumns(QuickLanguageZhButton, QuickLanguageEnButton),
|
|
QuickLabel("关闭按钮", "Close button"),
|
|
QuickColumns(QuickCloseAskButton, QuickCloseMinimizeButton, QuickCloseExitButton)),
|
|
QuickSettingsCard("运行选项", "Runtime options", "\uE7F4",
|
|
QuickProxySwitch,
|
|
QuickUpdateSwitch,
|
|
QuickHardwareAccelerationSwitch,
|
|
QuickPluginSwitch),
|
|
QuickOpenSettingsButton
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
return new Grid
|
|
{
|
|
Visibility = Visibility.Collapsed,
|
|
Opacity = 0,
|
|
Children = { QuickSettingsScrim, QuickSettingsPanel }
|
|
};
|
|
}
|
|
|
|
private static Button CreateIconButton(string glyph, string tooltip)
|
|
{
|
|
var button = new Button
|
|
{
|
|
Width = 34,
|
|
Height = 34,
|
|
Padding = new Thickness(0),
|
|
CornerRadius = new CornerRadius(6),
|
|
UseSystemFocusVisuals = true,
|
|
Background = ModernUi.Brush("#00FFFFFF"),
|
|
BorderBrush = ModernUi.Brush("#00FFFFFF"),
|
|
Content = new FontIcon { Glyph = glyph, FontSize = 15 }
|
|
};
|
|
ToolTipService.SetToolTip(button, tooltip);
|
|
AutomationProperties.SetName(button, tooltip);
|
|
return button;
|
|
}
|
|
|
|
private static Button QuickOptionButton(string zh, string en)
|
|
{
|
|
var label = AppLocalizer.T(zh, en);
|
|
var button = new Button
|
|
{
|
|
Content = label,
|
|
Tag = new LocalizedText(zh, en),
|
|
HorizontalAlignment = HorizontalAlignment.Stretch,
|
|
Padding = new Thickness(10, 7, 10, 7),
|
|
CornerRadius = new CornerRadius(6),
|
|
BorderThickness = new Thickness(1),
|
|
UseSystemFocusVisuals = true
|
|
};
|
|
ToolTipService.SetToolTip(button, label);
|
|
AutomationProperties.SetName(button, label);
|
|
return button;
|
|
}
|
|
|
|
private static ToggleSwitch QuickSwitch(string zh, string en)
|
|
{
|
|
var label = AppLocalizer.T(zh, en);
|
|
var toggle = new ToggleSwitch
|
|
{
|
|
Header = label,
|
|
Tag = new LocalizedText(zh, en),
|
|
HorizontalAlignment = HorizontalAlignment.Stretch
|
|
};
|
|
AutomationProperties.SetName(toggle, label);
|
|
return toggle;
|
|
}
|
|
|
|
private static TextBlock QuickLabel(string zh, string en)
|
|
{
|
|
return QuickText(zh, en, 13, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 1);
|
|
}
|
|
|
|
private static Grid QuickColumns(params FrameworkElement?[] elements)
|
|
{
|
|
var grid = new Grid { ColumnSpacing = 8 };
|
|
var column = 0;
|
|
foreach (var element in elements.Where(element => element is not null))
|
|
{
|
|
grid.ColumnDefinitions.Add(new ColumnDefinition());
|
|
Grid.SetColumn(element!, column++);
|
|
grid.Children.Add(element!);
|
|
}
|
|
|
|
return grid;
|
|
}
|
|
|
|
private static Border QuickSettingsCard(string zh, string en, string glyph, params UIElement?[] rows)
|
|
{
|
|
var stack = new StackPanel { Spacing = 12 };
|
|
stack.Children.Add(new StackPanel
|
|
{
|
|
Orientation = Orientation.Horizontal,
|
|
Spacing = 10,
|
|
Children =
|
|
{
|
|
ModernUi.IconTile(glyph, 32, ModernUi.SurfaceAlt, ModernUi.Accent, 15),
|
|
QuickText(zh, en, 18, FontWeights.SemiBold)
|
|
}
|
|
});
|
|
foreach (var row in rows.Where(row => row is not null))
|
|
{
|
|
stack.Children.Add(row!);
|
|
}
|
|
|
|
return ModernUi.Card(stack, new Thickness(16), radius: 6);
|
|
}
|
|
|
|
private static TextBlock QuickText(string zh, string en, double size, FontWeight? weight = null, Brush? foreground = null, int maxLines = 0)
|
|
{
|
|
var text = ModernUi.Text(AppLocalizer.T(zh, en), size, weight, foreground, maxLines);
|
|
text.Tag = new LocalizedText(zh, en);
|
|
return text;
|
|
}
|
|
}
|