Add battery percentage display next to clock and date

- Add PowerStatus NuGet package (v1.0.3)
- Add UseBattery setting to Settings.cs
- Add BatteryText property and update periodic timer in MainViewModel
- Add BatteryBox TextBlock to ClockPanel in MainWindow.xaml
- Add BaseBatteryBox and BatteryBox styles to Base.xaml and all theme files
- Add UseBattery toggle and preview to SettingsPaneTheme
- Add Battery localization string to en.xaml

Co-authored-by: Jack251970 <53996452+Jack251970@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-03-04 04:48:28 +00:00
parent bdf1d7c9ad
commit 4b62a1f29d
26 changed files with 183 additions and 3 deletions

View file

@ -165,6 +165,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool UseClock { get; set; } = true;
public bool UseDate { get; set; } = false;
public bool UseBattery { get; set; } = false;
public string TimeFormat { get; set; } = "hh:mm tt";
public string DateFormat { get; set; } = "MM'/'dd ddd";
public bool FirstLaunch { get; set; } = true;

View file

@ -109,7 +109,7 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.9" />
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
<PackageReference Include="PowerStatus" Version="*" />
<PackageReference Include="PowerStatus" Version="1.0.3" />
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>

View file

@ -328,6 +328,7 @@
<system:String x:Key="AnimationSpeedCustom">Custom</system:String>
<system:String x:Key="Clock">Clock</system:String>
<system:String x:Key="Date">Date</system:String>
<system:String x:Key="Battery">Battery</system:String>
<system:String x:Key="BackdropType">Backdrop Type</system:String>
<system:String x:Key="BackdropInfo">The backdrop effect is not applied in the preview.</system:String>
<system:String x:Key="BackdropTypeDisabledToolTip">Backdrop supported starting from Windows 11 build 22000 and above</system:String>

View file

@ -311,6 +311,11 @@
Style="{DynamicResource DateBox}"
Text="{Binding DateText}"
Visibility="{Binding Settings.UseDate, Converter={StaticResource BoolToVisibilityConverter}}" />
<TextBlock
x:Name="BatteryBox"
Style="{DynamicResource BatteryBox}"
Text="{Binding BatteryText}"
Visibility="{Binding Settings.UseBattery, Converter={StaticResource BoolToVisibilityConverter}}" />
</StackPanel>
<Border>
<Grid WindowChrome.IsHitTestVisibleInChrome="True">

View file

@ -296,6 +296,14 @@ public partial class SettingsPaneThemeViewModel : BaseModel
set => Settings.UseDate = value;
}
public bool UseBattery
{
get => Settings.UseBattery;
set => Settings.UseBattery = value;
}
public string BatteryText => "75%";
public FontFamily ClockPanelFont { get; }
public Brush PreviewBackground

View file

@ -348,6 +348,12 @@
Style="{DynamicResource DateBox}"
Text="{Binding DateText}"
Visibility="{Binding UseDate, Converter={StaticResource BoolToVisibilityConverter}}" />
<TextBlock
x:Name="BatteryBox"
FontFamily="{Binding ClockPanelFont, Mode=OneTime}"
Style="{DynamicResource BatteryBox}"
Text="{Binding BatteryText}"
Visibility="{Binding UseBattery, Converter={StaticResource BoolToVisibilityConverter}}" />
</StackPanel>
<Canvas Style="{DynamicResource SearchIconPosition}">
<Path
@ -612,6 +618,17 @@
</StackPanel>
</ui:SettingsCard>
<ui:SettingsCard Margin="0 4 0 0" Header="{DynamicResource Battery}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Glyph="&#xec02;" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch
IsOn="{Binding UseBattery}"
OffContent="{DynamicResource disable}"
OnContent="{DynamicResource enable}" />
</ui:SettingsCard>
<!-- Placeholder text -->
<ui:SettingsExpander
Margin="0 4 0 0"

View file

@ -152,6 +152,19 @@
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="BaseBatteryBox" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="18" />
<Setter Property="Foreground" Value="#8f8f8f" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0 0 0 0" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ClockBox, Path=Visibility}" Value="Visible">
<Setter Property="FontSize" Value="14" />
<Setter Property="Margin" Value="0 0 0 3" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style
x:Key="ClockBox"
@ -165,6 +178,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#C6C6C6" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#C6C6C6" />
</Style>
<Style
x:Key="ClockPanel"
BasedOn="{StaticResource BaseClockPanel}"

View file

@ -174,6 +174,13 @@
<Setter Property="Foreground" Value="#ffffff" />
<Setter Property="Opacity" Value="0.2" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#ffffff" />
<Setter Property="Opacity" Value="0.2" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -178,6 +178,13 @@
<Setter Property="Foreground" Value="#000000" />
<Setter Property="Opacity" Value="0.2" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#000000" />
<Setter Property="Opacity" Value="0.2" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -173,6 +173,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#999aa3" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#999aa3" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -183,6 +183,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#57c0b2" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#57c0b2" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -168,6 +168,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#6f737a" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#6f737a" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -166,6 +166,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#72767d" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#72767d" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -166,6 +166,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#6272a4" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#6272a4" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -163,6 +163,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#b7babe" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#b7babe" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -140,6 +140,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#4bb44b" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#4bb44b" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -163,6 +163,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#5f6673" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#5f6673" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -140,6 +140,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#6F7C95" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#6F7C95" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -137,6 +137,13 @@
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="#71114b" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="#71114b" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -222,6 +222,19 @@
</DataTrigger>
</Style.Triggers>
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="14" />
<Setter Property="Foreground" Value="#bebebe" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ClockBox, Path=Visibility}" Value="Visible">
<Setter Property="FontSize" Value="14" />
<Setter Property="Margin" Value="0 0 0 3" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -163,6 +163,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#5bafb0" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#5bafb0" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -180,6 +180,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#c2c2c2" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#c2c2c2" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -190,6 +190,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource SystemControlBackgroundBaseLowBrush}" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource SystemControlBackgroundBaseLowBrush}" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -215,6 +215,12 @@
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource ClockDateForeground}" />
</Style>
<Style
x:Key="BatteryBox"
BasedOn="{StaticResource BaseBatteryBox}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource ClockDateForeground}" />
</Style>
<Style
x:Key="PreviewBorderStyle"
BasedOn="{StaticResource BasePreviewBorderStyle}"

View file

@ -27,6 +27,7 @@ using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.Storage;
using iNKORE.UI.WPF.Modern;
using Microsoft.VisualStudio.Threading;
using PowerStatus;
namespace Flow.Launcher.ViewModel
{
@ -67,6 +68,8 @@ namespace Flow.Launcher.ViewModel
private bool _taskbarShownByFlow = false;
private readonly PowerStatusProvider _powerStatusProvider = new();
#endregion
#region Constructor
@ -336,6 +339,13 @@ namespace Flow.Launcher.ViewModel
ClockText = DateTime.Now.ToString(Settings.TimeFormat, CultureInfo.CurrentCulture);
if (Settings.UseDate)
DateText = DateTime.Now.ToString(Settings.DateFormat, CultureInfo.CurrentCulture);
if (Settings.UseBattery)
{
var status = _powerStatusProvider.GetStatus();
BatteryText = status.BatteryLifeProportion.HasValue
? $"{(int)(status.BatteryLifeProportion.Value * 100)}%"
: string.Empty;
}
}
}
@ -692,6 +702,7 @@ namespace Flow.Launcher.ViewModel
public Settings Settings { get; }
public string ClockText { get; private set; }
public string DateText { get; private set; }
public string BatteryText { get; private set; }
public ResultsViewModel Results { get; private set; }

View file

@ -135,6 +135,12 @@
"System.ValueTuple": "4.5.0"
}
},
"PowerStatus": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "kDqm6puX7icNM9wX6OdmruBXZAM9bX2XwNNBB9KmQf9/D8wqyixYYVnZF6U3WGs+qtyNIpPIflRaQ4wwzoRfJQ=="
},
"PropertyChanged.Fody": {
"type": "Direct",
"requested": "[4.1.0, )",
@ -1619,7 +1625,7 @@
"FSharp.Core": "[9.0.303, )",
"Flow.Launcher.Infrastructure": "[1.0.0, )",
"Flow.Launcher.Localization": "[0.0.6, )",
"Flow.Launcher.Plugin": "[5.0.0, )",
"Flow.Launcher.Plugin": "[5.2.0, )",
"Meziantou.Framework.Win32.Jobs": "[3.4.5, )",
"Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )",
"SemanticVersioning": "[3.0.0, )",
@ -1634,7 +1640,7 @@
"BitFaster.Caching": "[2.5.4, )",
"CommunityToolkit.Mvvm": "[8.4.0, )",
"Flow.Launcher.Localization": "[0.0.6, )",
"Flow.Launcher.Plugin": "[5.0.0, )",
"Flow.Launcher.Plugin": "[5.2.0, )",
"InputSimulator": "[1.0.4, )",
"MemoryPack": "[1.21.4, )",
"Microsoft.VisualStudio.Threading": "[17.14.15, )",