Skip to content

Commit

Permalink
feat: add battery statistics UI
Browse files Browse the repository at this point in the history
  • Loading branch information
timschneeb committed May 4, 2024
1 parent 7df2385 commit 4a75f10
Show file tree
Hide file tree
Showing 31 changed files with 246 additions and 86 deletions.
90 changes: 38 additions & 52 deletions GalaxyBudsClient/GalaxyBudsClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,18 @@
<!-- Resources -->
<ItemGroup>
<AvaloniaResource Include="Resources\**" />
<AvaloniaResource Include="i18n\*"/>
<AvaloniaResource Include="i18n\*" />

<Compile Update="**\*.axaml.cs">
<DependentUpon>%(Filename)</DependentUpon>
<SubType>Code</SubType>
</Compile>

<Compile Remove="bin\**"/>
<AvaloniaResource Remove="bin\**"/>
<AvaloniaXaml Remove="bin\**"/>
<EmbeddedResource Remove="bin\**"/>
<None Remove="bin\**"/>
<Compile Update="Interface\Pages\RenamePage.axaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Interface\Pages\FmmConfigPage.axaml.cs">
<DependentUpon>FmmPage.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Interface\Pages\UsageReportPage.axaml.cs">
<DependentUpon>UsageReportPage.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Remove="bin\**" />
<AvaloniaResource Remove="bin\**" />
<AvaloniaXaml Remove="bin\**" />
<EmbeddedResource Remove="bin\**" />
<None Remove="bin\**" />
</ItemGroup>

<!-- Dependencies -->
Expand All @@ -82,71 +71,68 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AsyncErrorHandler.Fody" Version="1.3.0" />
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Controls.DataGrid" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Desktop" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Markup.Xaml.Loader" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Themes.Fluent" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Desktop" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Markup.Xaml.Loader" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.ReactiveUI" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Svg.Skia" Version="11.1.0-beta1"/>
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.1.0-beta1"/>
<PackageReference Include="Avalonia.Svg.Skia" Version="11.1.0-beta1" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.1.0-beta1" />
<PackageReference Include="AvaloniaHex" Version="0.1.0" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.0"/>
<PackageReference Include="CommandLineParser" Version="2.9.2-ci-210"/>
<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.0" />
<PackageReference Include="CommandLineParser" Version="2.9.2-ci-210" />
<PackageReference Include="Config.Net" Version="5.2.0" />
<PackageReference Include="CS-Script" Version="4.8.14" />
<PackageReference Include="FluentAvalonia.BreadcrumbBar" Version="2.0.2"/>
<PackageReference Include="FluentAvaloniaUI" Version="2.1.0-preview2" />
<PackageReference Include="FluentAvalonia.BreadcrumbBar" Version="2.0.2" />
<PackageReference Include="FluentAvaloniaUI" Version="2.1.0-preview4" />
<PackageReference Include="FluentIcons.Avalonia.Fluent" Version="1.1.234-exp" />
<PackageReference Include="InputSimulatorCore" Version="1.0.5"/>
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="6.0.0"/>
<PackageReference Include="InputSimulatorCore" Version="1.0.5" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0-preview.3.24172.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0-preview.3.24172.4" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0"/>
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41"/>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageReference Include="ScottPlot.Avalonia" Version="5.0.32" />
<PackageReference Include="Sentry" Version="4.2.1" />
<PackageReference Include="Sentry.Serilog" Version="4.2.1" />
<PackageReference Include="Serilog" Version="3.1.1"/>
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1"/>
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0"/>
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0"/>
<PackageReference Include="Serilog.Sinks.Trace" Version="3.0.0"/>
<PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Trace" Version="3.0.0" />
<PackageReference Include="SharpHook" Version="5.3.2" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0"/>
<PackageReference Include="Tmds.DBus" Version="0.16.0"/>
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageReference Include="Tmds.DBus" Version="0.16.0" />
<PackageReference Include="Visualize.Fody" Version="1.2.0" PrivateAssets="All" />
</ItemGroup>

<!-- Project references -->
<ItemGroup Condition="'$(IsWindows)'=='true'">
<ProjectReference Include="..\GalaxyBudsClient.Bluetooth.WindowsRT\GalaxyBudsClient.Bluetooth.WindowsRT.csproj"/>
<ProjectReference Include="..\GalaxyBudsClient.Bluetooth.Windows\GalaxyBudsClient.Bluetooth.Windows.csproj"/>
<ProjectReference Include="..\ThePBone.Interop.Win32\ThePBone.Interop.Win32.csproj"/>
<ProjectReference Include="..\GalaxyBudsClient.Bluetooth.WindowsRT\GalaxyBudsClient.Bluetooth.WindowsRT.csproj" />
<ProjectReference Include="..\GalaxyBudsClient.Bluetooth.Windows\GalaxyBudsClient.Bluetooth.Windows.csproj" />
<ProjectReference Include="..\ThePBone.Interop.Win32\ThePBone.Interop.Win32.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(IsLinux)'=='true'">
<ProjectReference Include="..\GalaxyBudsClient.Bluetooth.Linux\GalaxyBudsClient.Bluetooth.Linux.csproj"/>
<ProjectReference Include="..\ThePBone.MprisClient\ThePBone.MprisClient.csproj"/>
<ProjectReference Include="..\GalaxyBudsClient.Bluetooth.Linux\GalaxyBudsClient.Bluetooth.Linux.csproj" />
<ProjectReference Include="..\ThePBone.MprisClient\ThePBone.MprisClient.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(IsOSX)'=='true'">
<ProjectReference Include="..\ThePBone.OSX.Native\ThePBone.OSX.Native.csproj"/>
<ProjectReference Include="..\ThePBone.OSX.Native\ThePBone.OSX.Native.csproj" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\GalaxyBudsClient.Generators\GalaxyBudsClient.Generators.csproj">
<OutputItemType>Analyzer</OutputItemType>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\GalaxyBudsClient.Bluetooth\GalaxyBudsClient.Bluetooth.csproj"/>
</ItemGroup>

<ItemGroup>
<AdditionalFiles Include="Interface\Pages\RenamePage.axaml" />
<ProjectReference Include="..\GalaxyBudsClient.Bluetooth\GalaxyBudsClient.Bluetooth.csproj" />
</ItemGroup>
</Project>
3 changes: 2 additions & 1 deletion GalaxyBudsClient/Interface/MainView.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public MainView()
new SystemInfoPageViewModel(),
new RenamePageViewModel(),
new FmmConfigPageViewModel(),
new UsageReportPageViewModel()
new UsageReportPageViewModel(),
new BatteryHistoryPageViewModel()
];

protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
Expand Down
37 changes: 37 additions & 0 deletions GalaxyBudsClient/Interface/Pages/BatteryHistoryPage.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<UserControl xmlns="https://github.com/avaloniaui"
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:controls="clr-namespace:GalaxyBudsClient.Interface.Controls"
xmlns:pages="clr-namespace:GalaxyBudsClient.Interface.ViewModels.Pages"
xmlns:ext="clr-namespace:GalaxyBudsClient.Interface.MarkupExtensions"
xmlns:i18N="clr-namespace:GalaxyBudsClient.Generated.I18N"
xmlns:config="clr-namespace:GalaxyBudsClient.Model.Config"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:plot="clr-namespace:ScottPlot.Avalonia;assembly=ScottPlot.Avalonia"
xmlns:control="clr-namespace:ScottPlot.Control;assembly=ScottPlot"
mc:Ignorable="d" d:DesignWidth="800"
x:Class="GalaxyBudsClient.Interface.Pages.BatteryHistoryPage"
x:DataType="pages:BatteryHistoryPageViewModel"
x:CompileBindings="True">

<Design.DataContext>
<pages:BatteryHistoryPageViewModel />
</Design.DataContext>

<Grid RowDefinitions="Auto,*"
Margin="{StaticResource AppPageMargin}">

<controls:CustomInfoBar Title="{ext:Translate {x:Static i18N:Keys.Hint}}"
Message="{ext:Translate {x:Static i18N:Keys.BattHistHint}}"
IsClosable="True"
IsOpen="{Binding !IsBatteryHistoryHintHidden, Source={x:Static config:Settings.Data}}"
Severity="Informational"
Closed="OnHintClosed"
Margin="0,0,0,8"/>

<!-- AvaPlot does not support bindings :( -->
<plot:AvaPlot Name="PlotControl"
Grid.Row="1" />
</Grid>
</UserControl>
24 changes: 24 additions & 0 deletions GalaxyBudsClient/Interface/Pages/BatteryHistoryPage.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using FluentAvalonia.UI.Controls;
using GalaxyBudsClient.Interface.ViewModels.Pages;
using GalaxyBudsClient.Model.Config;

namespace GalaxyBudsClient.Interface.Pages;

public partial class BatteryHistoryPage : BasePage<BatteryHistoryPageViewModel>
{
public BatteryHistoryPage()
{
InitializeComponent();
}

protected override void OnInitialized()
{
ViewModel!.Plot = PlotControl.Plot;
base.OnInitialized();
}

private void OnHintClosed(InfoBar sender, InfoBarClosedEventArgs args)
{
Settings.Data.IsBatteryHistoryHintHidden = true;
}
}
6 changes: 2 additions & 4 deletions GalaxyBudsClient/Interface/Pages/SystemPage.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,12 @@
</Interaction.Behaviors>
</controls:SettingsSymbolItem>

<!-- TODO Add battery statistics -->
<!--<controls:SettingsSymbolItem Name="BatteryStatistic"
<controls:SettingsSymbolItem Name="BatteryHistory"
Content="{ext:Translate {x:Static i18N:Keys.SystemBatteryStatistics}}"
Description="{ext:Translate {x:Static i18N:Keys.SystemBatteryStatisticsDesc}}"
Symbol="DataTrending"
ActionSymbol="ChevronRight"
IsClickEnabled="True" />-->

IsClickEnabled="True" />
</controls:SettingsGroup>

<controls:SettingsGroup>
Expand Down
4 changes: 1 addition & 3 deletions GalaxyBudsClient/Interface/ViewModels/MainViewViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ public Control GetPageFromObject(object target)
if (target is not PageViewModelBase model)
throw new ArgumentException("Target must derive from ViewModelBase");

var view = model.CreateView();
view.DataContext = model;
return view;
return model.CreateView();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace GalaxyBudsClient.Interface.ViewModels.Pages;

public class AdvancedPageViewModel : MainPageViewModelBase
{
public override Control CreateView() => new AdvancedPage();
public override Control CreateView() => new AdvancedPage { DataContext = this };

public AdvancedPageViewModel()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace GalaxyBudsClient.Interface.ViewModels.Pages;

public class AmbientCustomizePageViewModel : SubPageViewModelBase
{
public override Control CreateView() => new AmbientCustomizePage();
public override Control CreateView() => new AmbientCustomizePage { DataContext = this };

public AmbientCustomizePageViewModel()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using GalaxyBudsClient.Generated.I18N;
using GalaxyBudsClient.Interface.Pages;
using GalaxyBudsClient.Utils;
using GalaxyBudsClient.Utils.Interface;
using Microsoft.EntityFrameworkCore;
using ReactiveUI.Fody.Helpers;
using ScottPlot;
using ScottPlot.AxisRules;
using ScottPlot.Control;
using ScottPlot.TickGenerators;

namespace GalaxyBudsClient.Interface.ViewModels.Pages;

public class BatteryHistoryPageViewModel : SubPageViewModelBase
{
public override Control CreateView() => new BatteryHistoryPage { DataContext = this };
public override string TitleKey => Keys.SystemBatteryStatistics;
public Plot? Plot { set; get; }

public BatteryHistoryPageViewModel()
{
}

public override async void OnNavigatedTo()
{
if(Plot == null)
return;

Plot.Clear();
Plot.Add.Palette = new ScottPlot.Palettes.Nord();

await using var disposableQuery = await BatteryHistoryManager.BeginDisposableQueryAsync();
var cutOffDate = DateTime.Now - TimeSpan.FromDays(1);

var query = disposableQuery.Queryable
.Where(record => record.Timestamp > cutOffDate);

var batteryL = new List<float>();
var batteryR = new List<float>();
var timestampL = new List<DateTime>();
var timestampR = new List<DateTime>();

await foreach (var record in query.AsAsyncEnumerable())
{
batteryL.Add(record.BatteryL > 0 ? record.BatteryL ?? float.NaN : float.NaN);
timestampL.Add(record.Timestamp);
batteryR.Add(record.BatteryR > 0 ? record.BatteryR ?? float.NaN : float.NaN);
timestampR.Add(record.Timestamp);
}

var plotBatteryL = Plot.Add.Scatter(timestampL, batteryL);
plotBatteryL.MarkerShape = MarkerShape.None;
plotBatteryL.LegendText = Strings.Left;

var plotBatteryR = Plot.Add.Scatter(timestampR, batteryR);
plotBatteryR.MarkerShape = MarkerShape.None;
plotBatteryR.LegendText = Strings.Right;


/*Plot.Axes.Rules.Add(new MaximumBoundary(Plot.Axes.Bottom, Plot.Axes.Left, new AxisLimits(new CoordinateRect
{
Right = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
Left = (DateTimeOffset.Now - TimeSpan.FromDays(7)).ToUnixTimeMilliseconds(),
Top = 105,
Bottom = 0
})));*/
Plot.Axes.Left.TickGenerator = new NumericAutomatic()
{
LabelFormatter = value => value is < 0 or > 100 ? string.Empty : NumericAutomatic.DefaultLabelFormatter(value),
};

Plot.YLabel("Charge (%)");
Plot.ShowLegend();

Plot?.Axes.DateTimeTicksBottom();
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ private async void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
[Reactive] public BixbyLanguages BixbyLanguage { set; get; }

public override string TitleKey => Keys.AdvBixbyRemap;
public override Control CreateView() => new BixbyRemapPage();
public override Control CreateView() => new BixbyRemapPage { DataContext = this };
}


Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace GalaxyBudsClient.Interface.ViewModels.Pages;

public class DevicesPageViewModel : MainPageViewModelBase
{
public override Control CreateView() => new DevicesPage();
public override Control CreateView() => new DevicesPage { DataContext = this };
public override string TitleKey => Keys.DevicesHeader;
public override Symbol IconKey => Symbol.BluetoothConnected;
public override bool ShowsInFooter => true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ There is no audible difference. */
StereoBalance = e.HearingEnhancements;
}

public override Control CreateView() => new EqualizerPage();
public override Control CreateView() => new EqualizerPage { DataContext = this };

[Reactive] public bool IsEqEnabled { set; get; }
[Reactive] public int EqPreset { set; get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace GalaxyBudsClient.Interface.ViewModels.Pages;

public class FindMyBudsPageViewModel : MainPageViewModelBase
{
public override Control CreateView() => new FindMyBudsPage();
public override Control CreateView() => new FindMyBudsPage { DataContext = this };
public override string TitleKey => Keys.FmgHeader;
public override Symbol IconKey => Symbol.LocationLive;
public override bool ShowsInFooter => false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace GalaxyBudsClient.Interface.ViewModels.Pages;

public class FirmwarePageViewModel : SubPageViewModelBase
{
public override Control CreateView() => new FirmwarePage();
public override Control CreateView() => new FirmwarePage { DataContext = this };
public override string TitleKey => Keys.FwSelectHeader;

[Reactive] public bool IsDowngradingAllowed { set; get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace GalaxyBudsClient.Interface.ViewModels.Pages;

public class FitTestPageViewModel : SubPageViewModelBase
{
public override Control CreateView() => new FitTestPage();
public override Control CreateView() => new FitTestPage { DataContext = this };
public override string TitleKey => Keys.MainpageFitTest;

[Reactive] public string? WarningText { set; get; }
Expand Down
Loading

0 comments on commit 4a75f10

Please sign in to comment.