Add sidebar.

This commit is contained in:
2025-11-14 19:00:01 +00:00
parent 955c2f9654
commit 7ede62514f
10 changed files with 877 additions and 348 deletions

View File

@@ -0,0 +1,59 @@
using System;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
namespace Marechai.App.Presentation.Converters;
/// <summary>
/// Converts boolean value to collapse/expand arrow icon
/// </summary>
public class CollapseExpandIconConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if(value is bool isOpen) return isOpen ? "◄" : "►";
return "►";
}
public object ConvertBack(object value, Type targetType, object parameter, string language) =>
throw new NotImplementedException();
}
/// <summary>
/// Converts boolean value to collapse/expand tooltip text
/// </summary>
public class CollapseExpandTooltipConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if(value is bool isOpen) return isOpen ? "Collapse Sidebar" : "Expand Sidebar";
return "Expand Sidebar";
}
public object ConvertBack(object value, Type targetType, object parameter, string language) =>
throw new NotImplementedException();
}
/// <summary>
/// Converts boolean value to GridLength for sidebar column width
/// </summary>
public class SidebarWidthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if(value is bool isOpen)
{
// 280 when open, 60 when collapsed (to keep toggle button visible)
double width = isOpen ? 280 : 60;
return new GridLength(width, GridUnitType.Pixel);
}
return new GridLength(280, GridUnitType.Pixel);
}
public object ConvertBack(object value, Type targetType, object parameter, string language) =>
throw new NotImplementedException();
}

View File

@@ -4,26 +4,55 @@
<Page x:Class="Marechai.App.Presentation.MainPage" <Page x:Class="Marechai.App.Presentation.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Marechai.App.Presentation"
xmlns:utu="using:Uno.Toolkit.UI" xmlns:utu="using:Uno.Toolkit.UI"
NavigationCacheMode="Required" NavigationCacheMode="Required"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid utu:SafeArea.Insets="VisibleBounds"> <Grid utu:SafeArea.Insets="VisibleBounds">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="SidebarColumn"
Width="280" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Header --> <!-- Sidebar -->
<utu:NavigationBar Content="{Binding Title}" /> <Grid x:Name="SidebarWrapper"
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
Width="280"
HorizontalAlignment="Left">
<local:Sidebar x:Name="SidebarPanel"
DataContext="{Binding}"
VerticalAlignment="Stretch" />
</Grid>
<!-- Refresh Container with Pull-to-Refresh --> <!-- Header -->
<RefreshContainer Grid.Row="1" <utu:NavigationBar Grid.Row="0"
x:Name="RefreshContainer" Grid.Column="1"
Content="{Binding Title}">
<utu:NavigationBar.MainCommand>
<AppBarButton Icon="GlobalNavigationButton"
Command="{Binding ToggleSidebarCommand}"
Label="Toggle Sidebar"
AutomationProperties.Name="Toggle sidebar visibility" />
</utu:NavigationBar.MainCommand>
</utu:NavigationBar>
<!-- Content -->
<Grid Grid.Row="1"
Grid.Column="1">
<RefreshContainer x:Name="RefreshContainer"
RefreshRequested="RefreshContainer_RefreshRequested"> RefreshRequested="RefreshContainer_RefreshRequested">
<ScrollViewer> <ScrollViewer>
<Grid Padding="16"> <Grid Padding="16">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- News Title Section --> <!-- News Title Section -->
@@ -129,4 +158,5 @@
</ScrollViewer> </ScrollViewer>
</RefreshContainer> </RefreshContainer>
</Grid> </Grid>
</Grid>
</Page> </Page>

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.ComponentModel;
using Windows.Foundation; using Windows.Foundation;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
@@ -9,15 +10,93 @@ namespace Marechai.App.Presentation;
public sealed partial class MainPage : Page public sealed partial class MainPage : Page
{ {
private bool _initialNewsLoaded; private bool _initialNewsLoaded;
private PropertyChangedEventHandler _sidebarPropertyChangedHandler;
public MainPage() public MainPage()
{ {
InitializeComponent(); InitializeComponent();
DataContextChanged += MainPage_DataContextChanged; DataContextChanged += MainPage_DataContextChanged;
Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if(DataContext is not MainViewModel viewModel) return;
SidebarWrapper.Width = viewModel.IsSidebarOpen ? 280 : 60;
if(_sidebarPropertyChangedHandler != null) return;
_sidebarPropertyChangedHandler = (_, propArgs) =>
{
if(propArgs.PropertyName != nameof(MainViewModel.IsSidebarOpen)) return;
AnimateSidebarWidth(((MainViewModel)DataContext).IsSidebarOpen);
};
((INotifyPropertyChanged)viewModel).PropertyChanged += _sidebarPropertyChangedHandler;
}
void AnimateSidebarWidth(bool isOpen)
{
double start = SidebarColumn.Width.Value;
double end = isOpen ? 280 : 60;
if(Math.Abs(start - end) < 0.1) return;
// If expanding, show content immediately
if(isOpen && DataContext is MainViewModel vm) vm.SidebarContentVisible = true;
const int durationMs = 250;
const int fps = 60;
var steps = (int)(durationMs / (1000.0 / fps));
var currentStep = 0;
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(1000.0 / fps)
};
timer.Tick += (_, _) =>
{
currentStep++;
double t = (double)currentStep / steps;
// Ease in-out cubic
double eased = t < 0.5 ? 4 * t * t * t : 1 - Math.Pow(-2 * t + 2, 3) / 2;
double value = start + (end - start) * eased;
SidebarColumn.Width = new GridLength(value, GridUnitType.Pixel);
SidebarWrapper.Width = value;
if(currentStep >= steps)
{
SidebarColumn.Width = new GridLength(end, GridUnitType.Pixel);
SidebarWrapper.Width = end;
timer.Stop();
// After collapse animation completes, hide sidebar content
if(!isOpen && DataContext is MainViewModel vm) vm.SidebarContentVisible = false;
}
};
timer.Start();
} }
private void MainPage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args) private void MainPage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{ {
if(args.NewValue is MainViewModel vm && _sidebarPropertyChangedHandler == null)
{
SidebarWrapper.Width = vm.IsSidebarOpen ? 280 : 60;
_sidebarPropertyChangedHandler = (_, propArgs) =>
{
if(propArgs.PropertyName != nameof(MainViewModel.IsSidebarOpen)) return;
AnimateSidebarWidth(vm.IsSidebarOpen);
};
((INotifyPropertyChanged)vm).PropertyChanged += _sidebarPropertyChangedHandler;
}
if(_initialNewsLoaded) return; if(_initialNewsLoaded) return;
if(args.NewValue is MainViewModel viewModel && viewModel.NewsViewModel is not null) if(args.NewValue is MainViewModel viewModel && viewModel.NewsViewModel is not null)

View File

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using Uno.Extensions.Navigation; using Uno.Extensions.Navigation;
@@ -6,30 +7,163 @@ namespace Marechai.App.Presentation;
public partial class MainViewModel : ObservableObject public partial class MainViewModel : ObservableObject
{ {
private readonly IStringLocalizer _localizer;
private readonly INavigator _navigator; private readonly INavigator _navigator;
[ObservableProperty]
private bool isSidebarOpen = true;
[ObservableProperty]
private Dictionary<string, string> localizedStrings = new();
[ObservableProperty]
private string loginLogoutButtonText = "";
[ObservableProperty] [ObservableProperty]
private string? name; private string? name;
[ObservableProperty] [ObservableProperty]
private NewsViewModel? newsViewModel; private NewsViewModel? newsViewModel;
[ObservableProperty]
private bool sidebarContentVisible = true;
public MainViewModel(IStringLocalizer localizer, IOptions<AppConfig> appInfo, INavigator navigator, public MainViewModel(IStringLocalizer localizer, IOptions<AppConfig> appInfo, INavigator navigator,
NewsViewModel newsViewModel) NewsViewModel newsViewModel)
{ {
_navigator = navigator; _navigator = navigator;
_localizer = localizer;
NewsViewModel = newsViewModel; NewsViewModel = newsViewModel;
Title = "Marechai"; Title = "Marechai";
Title += $" - {localizer["ApplicationName"]}"; Title += $" - {localizer["ApplicationName"]}";
Title += $" - {appInfo?.Value?.Environment}"; if(appInfo?.Value?.Environment != null) Title += $" - {appInfo.Value.Environment}";
GoToSecond = new AsyncRelayCommand(GoToSecondView); GoToSecond = new AsyncRelayCommand(GoToSecondView);
// Initialize localized strings
InitializeLocalizedStrings();
// Initialize commands
NavigateToNewsCommand = new AsyncRelayCommand(NavigateToMainAsync);
NavigateToBooksCommand = new AsyncRelayCommand(() => NavigateTo("books"));
NavigateToCompaniesCommand = new AsyncRelayCommand(() => NavigateTo("companies"));
NavigateToComputersCommand = new AsyncRelayCommand(() => NavigateTo("computers"));
NavigateToConsolesCommand = new AsyncRelayCommand(() => NavigateTo("consoles"));
NavigateToDocumentsCommand = new AsyncRelayCommand(() => NavigateTo("documents"));
NavigateToDumpsCommand = new AsyncRelayCommand(() => NavigateTo("dumps"));
NavigateToGraphicalProcessingUnitsCommand = new AsyncRelayCommand(() => NavigateTo("gpus"));
NavigateToMagazinesCommand = new AsyncRelayCommand(() => NavigateTo("magazines"));
NavigateToPeopleCommand = new AsyncRelayCommand(() => NavigateTo("people"));
NavigateToProcessorsCommand = new AsyncRelayCommand(() => NavigateTo("processors"));
NavigateToSoftwareCommand = new AsyncRelayCommand(() => NavigateTo("software"));
NavigateToSoundSynthesizersCommand = new AsyncRelayCommand(() => NavigateTo("soundsynthesizers"));
NavigateToSettingsCommand = new AsyncRelayCommand(() => NavigateTo("settings"));
LoginLogoutCommand = new RelayCommand(HandleLoginLogout);
ToggleSidebarCommand = new RelayCommand(() => IsSidebarOpen = !IsSidebarOpen);
UpdateLoginLogoutButtonText();
} }
public string? Title { get; } public string? Title { get; }
public ICommand GoToSecond { get; } public ICommand GoToSecond { get; }
public ICommand NavigateToNewsCommand { get; }
public ICommand NavigateToBooksCommand { get; }
public ICommand NavigateToCompaniesCommand { get; }
public ICommand NavigateToComputersCommand { get; }
public ICommand NavigateToConsolesCommand { get; }
public ICommand NavigateToDocumentsCommand { get; }
public ICommand NavigateToDumpsCommand { get; }
public ICommand NavigateToGraphicalProcessingUnitsCommand { get; }
public ICommand NavigateToMagazinesCommand { get; }
public ICommand NavigateToPeopleCommand { get; }
public ICommand NavigateToProcessorsCommand { get; }
public ICommand NavigateToSoftwareCommand { get; }
public ICommand NavigateToSoundSynthesizersCommand { get; }
public ICommand NavigateToSettingsCommand { get; }
public ICommand LoginLogoutCommand { get; }
public ICommand ToggleSidebarCommand { get; }
private void InitializeLocalizedStrings()
{
LocalizedStrings = new Dictionary<string, string>
{
{
"News", _localizer["News"]
},
{
"Books", _localizer["Books"]
},
{
"Companies", _localizer["Companies"]
},
{
"Computers", _localizer["Computers"]
},
{
"Consoles", _localizer["Consoles"]
},
{
"Documents", _localizer["Documents"]
},
{
"Dumps", _localizer["Dumps"]
},
{
"GraphicalProcessingUnits", _localizer["GraphicalProcessingUnits"]
},
{
"Magazines", _localizer["Magazines"]
},
{
"People", _localizer["People"]
},
{
"Processors", _localizer["Processors"]
},
{
"Software", _localizer["Software"]
},
{
"SoundSynthesizers", _localizer["SoundSynthesizers"]
},
{
"Settings", _localizer["Settings"]
},
{
"Login", _localizer["Login"]
},
{
"Logout", _localizer["Logout"]
}
};
}
private void UpdateLoginLogoutButtonText()
{
// TODO: Check if user is logged in
// For now, always show "Login"
LoginLogoutButtonText = LocalizedStrings["Login"];
}
private static void HandleLoginLogout()
{
// TODO: Implement login/logout logic
}
private async Task NavigateTo(string destination)
{
// TODO: Navigate to the specified destination
// These routes will need to be registered in App.xaml.cs RegisterRoutes method
// For now, placeholder implementation
await Task.CompletedTask;
}
private async Task NavigateToMainAsync()
{
// Stay on main page
await Task.CompletedTask;
}
private async Task GoToSecondView() private async Task GoToSecondView()
{ {
await _navigator.NavigateViewModelAsync<SecondViewModel>(this, data: new Entity(Name!)); // Navigate to Second view model providing qualifier and data
await _navigator.NavigateViewModelAsync<SecondViewModel>(this, "Second", new Entity(Name ?? ""));
} }
} }

View File

@@ -0,0 +1,260 @@
<?xml version="1.0"
encoding="utf-8"?>
<UserControl x:Class="Marechai.App.Presentation.Sidebar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="using:Marechai.App.Presentation.Converters"
mc:Ignorable="d"
d:DesignHeight="600"
d:DesignWidth="280"
Background="{ThemeResource NavigationViewDefaultPaneBackground}">
<UserControl.Resources>
<local:CollapseExpandIconConverter x:Key="CollapseExpandIconConverter" />
<local:CollapseExpandTooltipConverter x:Key="CollapseExpandTooltipConverter" />
</UserControl.Resources>
<!-- Grid container - naturally responds to parent column width -->
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Sidebar Header with Collapse/Expand Button -->
<Grid Grid.Row="0"
Padding="8,8,8,8"
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
BorderThickness="0,0,0,1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Sidebar Title - Hidden when collapsed -->
<TextBlock Grid.Column="0"
Text="Navigation"
FontSize="16"
FontWeight="SemiBold"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
VerticalAlignment="Center"
Padding="4,0,0,0"
Visibility="{Binding SidebarContentVisible}" />
<!-- Collapse/Expand Button - Always visible -->
<Button Grid.Column="1"
Content="{Binding IsSidebarOpen, Converter={StaticResource CollapseExpandIconConverter}}"
Command="{Binding ToggleSidebarCommand}"
Background="Transparent"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Padding="8,8,8,8"
CornerRadius="4"
ToolTipService.ToolTip="{Binding IsSidebarOpen, Converter={StaticResource CollapseExpandTooltipConverter}}"
FontSize="14"
MinWidth="40"
MinHeight="40"
HorizontalAlignment="Center" />
</Grid>
<!-- Scrollable Navigation Items - Hidden when collapsed -->
<ScrollViewer Grid.Row="1"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
Padding="0"
Visibility="{Binding SidebarContentVisible}">
<StackPanel Orientation="Vertical"
Spacing="0"
Padding="0">
<!-- News -->
<Button Content="{Binding LocalizedStrings[News]}"
Command="{Binding NavigateToNewsCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Books -->
<Button Content="{Binding LocalizedStrings[Books]}"
Command="{Binding NavigateToBooksCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Companies -->
<Button Content="{Binding LocalizedStrings[Companies]}"
Command="{Binding NavigateToCompaniesCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Computers -->
<Button Content="{Binding LocalizedStrings[Computers]}"
Command="{Binding NavigateToComputersCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Consoles -->
<Button Content="{Binding LocalizedStrings[Consoles]}"
Command="{Binding NavigateToConsolesCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Documents -->
<Button Content="{Binding LocalizedStrings[Documents]}"
Command="{Binding NavigateToDocumentsCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Dumps -->
<Button Content="{Binding LocalizedStrings[Dumps]}"
Command="{Binding NavigateToDumpsCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Graphical Processing Units -->
<Button Content="{Binding LocalizedStrings[GraphicalProcessingUnits]}"
Command="{Binding NavigateToGraphicalProcessingUnitsCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Magazines -->
<Button Content="{Binding LocalizedStrings[Magazines]}"
Command="{Binding NavigateToMagazinesCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- People -->
<Button Content="{Binding LocalizedStrings[People]}"
Command="{Binding NavigateToPeopleCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Processors -->
<Button Content="{Binding LocalizedStrings[Processors]}"
Command="{Binding NavigateToProcessorsCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Software -->
<Button Content="{Binding LocalizedStrings[Software]}"
Command="{Binding NavigateToSoftwareCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Sound Synthesizers -->
<Button Content="{Binding LocalizedStrings[SoundSynthesizers]}"
Command="{Binding NavigateToSoundSynthesizersCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
</StackPanel>
</ScrollViewer>
<!-- Bottom Fixed Items - Hidden when collapsed -->
<Grid Grid.Row="2"
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
BorderThickness="0,1,0,0"
Padding="0"
Visibility="{Binding IsSidebarOpen}">
<StackPanel Orientation="Vertical"
Spacing="0">
<!-- Login/Logout -->
<Button Content="{Binding LoginLogoutButtonText}"
Command="{Binding LoginLogoutCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
<!-- Settings -->
<Button Content="{Binding LocalizedStrings[Settings]}"
Command="{Binding NavigateToSettingsCommand}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="16,10,16,10"
FontSize="13"
Background="Transparent"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
BorderThickness="0"
CornerRadius="0" />
</StackPanel>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,11 @@
using Microsoft.UI.Xaml.Controls;
namespace Marechai.App.Presentation;
public sealed partial class Sidebar : UserControl
{
public Sidebar()
{
InitializeComponent();
}
}

View File

@@ -1,64 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
@@ -120,4 +61,52 @@
<data name="ApplicationName" xml:space="preserve"> <data name="ApplicationName" xml:space="preserve">
<value>Marechai.App-en</value> <value>Marechai.App-en</value>
</data> </data>
<data name="News" xml:space="preserve">
<value>News</value>
</data>
<data name="Books" xml:space="preserve">
<value>Books</value>
</data>
<data name="Companies" xml:space="preserve">
<value>Companies</value>
</data>
<data name="Computers" xml:space="preserve">
<value>Computers</value>
</data>
<data name="Consoles" xml:space="preserve">
<value>Consoles</value>
</data>
<data name="Documents" xml:space="preserve">
<value>Documents</value>
</data>
<data name="Dumps" xml:space="preserve">
<value>Dumps</value>
</data>
<data name="GraphicalProcessingUnits" xml:space="preserve">
<value>Graphical Processing Units</value>
</data>
<data name="Magazines" xml:space="preserve">
<value>Magazines</value>
</data>
<data name="People" xml:space="preserve">
<value>People</value>
</data>
<data name="Processors" xml:space="preserve">
<value>Processors</value>
</data>
<data name="Software" xml:space="preserve">
<value>Software</value>
</data>
<data name="SoundSynthesizers" xml:space="preserve">
<value>Sound Synthesizers</value>
</data>
<data name="Settings" xml:space="preserve">
<value>Settings</value>
</data>
<data name="Login" xml:space="preserve">
<value>Login</value>
</data>
<data name="Logout" xml:space="preserve">
<value>Logout</value>
</data>
</root> </root>

View File

@@ -1,64 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
@@ -120,4 +61,52 @@
<data name="ApplicationName" xml:space="preserve"> <data name="ApplicationName" xml:space="preserve">
<value>Marechai.App-es</value> <value>Marechai.App-es</value>
</data> </data>
<data name="News" xml:space="preserve">
<value>Noticias</value>
</data>
<data name="Books" xml:space="preserve">
<value>Libros</value>
</data>
<data name="Companies" xml:space="preserve">
<value>Empresas</value>
</data>
<data name="Computers" xml:space="preserve">
<value>Computadoras</value>
</data>
<data name="Consoles" xml:space="preserve">
<value>Consolas</value>
</data>
<data name="Documents" xml:space="preserve">
<value>Documentos</value>
</data>
<data name="Dumps" xml:space="preserve">
<value>Volcados</value>
</data>
<data name="GraphicalProcessingUnits" xml:space="preserve">
<value>Unidades de Procesamiento Gráfico</value>
</data>
<data name="Magazines" xml:space="preserve">
<value>Revistas</value>
</data>
<data name="People" xml:space="preserve">
<value>Personas</value>
</data>
<data name="Processors" xml:space="preserve">
<value>Procesadores</value>
</data>
<data name="Software" xml:space="preserve">
<value>Software</value>
</data>
<data name="SoundSynthesizers" xml:space="preserve">
<value>Sintetizadores de Sonido</value>
</data>
<data name="Settings" xml:space="preserve">
<value>Configuración</value>
</data>
<data name="Login" xml:space="preserve">
<value>Iniciar sesión</value>
</data>
<data name="Logout" xml:space="preserve">
<value>Cerrar sesión</value>
</data>
</root> </root>

View File

@@ -1,64 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
@@ -120,4 +61,52 @@
<data name="ApplicationName" xml:space="preserve"> <data name="ApplicationName" xml:space="preserve">
<value>Marechai.App-fr</value> <value>Marechai.App-fr</value>
</data> </data>
<data name="News" xml:space="preserve">
<value>Actualités</value>
</data>
<data name="Books" xml:space="preserve">
<value>Livres</value>
</data>
<data name="Companies" xml:space="preserve">
<value>Entreprises</value>
</data>
<data name="Computers" xml:space="preserve">
<value>Ordinateurs</value>
</data>
<data name="Consoles" xml:space="preserve">
<value>Consoles</value>
</data>
<data name="Documents" xml:space="preserve">
<value>Documents</value>
</data>
<data name="Dumps" xml:space="preserve">
<value>Vidages</value>
</data>
<data name="GraphicalProcessingUnits" xml:space="preserve">
<value>Processeurs Graphiques</value>
</data>
<data name="Magazines" xml:space="preserve">
<value>Magazines</value>
</data>
<data name="People" xml:space="preserve">
<value>Personnes</value>
</data>
<data name="Processors" xml:space="preserve">
<value>Processeurs</value>
</data>
<data name="Software" xml:space="preserve">
<value>Logiciels</value>
</data>
<data name="SoundSynthesizers" xml:space="preserve">
<value>Synthétiseurs de Son</value>
</data>
<data name="Settings" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="Login" xml:space="preserve">
<value>Connexion</value>
</data>
<data name="Logout" xml:space="preserve">
<value>Déconnexion</value>
</data>
</root> </root>

View File

@@ -1,64 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
@@ -120,4 +61,52 @@
<data name="ApplicationName" xml:space="preserve"> <data name="ApplicationName" xml:space="preserve">
<value>Marechai.App-pt-BR</value> <value>Marechai.App-pt-BR</value>
</data> </data>
<data name="News" xml:space="preserve">
<value>Notícias</value>
</data>
<data name="Books" xml:space="preserve">
<value>Livros</value>
</data>
<data name="Companies" xml:space="preserve">
<value>Empresas</value>
</data>
<data name="Computers" xml:space="preserve">
<value>Computadores</value>
</data>
<data name="Consoles" xml:space="preserve">
<value>Consoles</value>
</data>
<data name="Documents" xml:space="preserve">
<value>Documentos</value>
</data>
<data name="Dumps" xml:space="preserve">
<value>Dumps</value>
</data>
<data name="GraphicalProcessingUnits" xml:space="preserve">
<value>Unidades de Processamento Gráfico</value>
</data>
<data name="Magazines" xml:space="preserve">
<value>Revistas</value>
</data>
<data name="People" xml:space="preserve">
<value>Pessoas</value>
</data>
<data name="Processors" xml:space="preserve">
<value>Processadores</value>
</data>
<data name="Software" xml:space="preserve">
<value>Software</value>
</data>
<data name="SoundSynthesizers" xml:space="preserve">
<value>Sintetizadores de Som</value>
</data>
<data name="Settings" xml:space="preserve">
<value>Configurações</value>
</data>
<data name="Login" xml:space="preserve">
<value>Fazer Login</value>
</data>
<data name="Logout" xml:space="preserve">
<value>Fazer Logout</value>
</data>
</root> </root>