Skip to content

Commit

Permalink
feat: Support for PowerManager on WASM
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Aug 21, 2023
1 parent eb00147 commit 95a5a2b
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
d:DesignHeight="2000"
d:DesignWidth="400">

<Grid RowSpacing="8" Padding="20">
<Grid RowSpacing="4" Padding="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public bool IsBatteryStatusChangedSubscribed
{
if (value)
{
UwpPowerManager.BatteryStatusChanged += UwpPowerManager_BatteryStatusChanged;
_batteryStatusChangedSubscription.Disposable = Disposable.Create(() =>
UwpPowerManager.BatteryStatusChanged -= UwpPowerManager_BatteryStatusChanged);
}
Expand All @@ -131,6 +132,7 @@ public bool IsEnergySaverStatusChangedSubscribed
{
if (value)
{
UwpPowerManager.EnergySaverStatusChanged += UwpPowerManager_EnergySaverStatusChanged;
_energySaverStatusChangedSubscription.Disposable = Disposable.Create(() =>
UwpPowerManager.EnergySaverStatusChanged -= UwpPowerManager_EnergySaverStatusChanged);
}
Expand All @@ -150,6 +152,7 @@ public bool IsPowerSupplyStatusChangedSubscribed
{
if (value)
{
UwpPowerManager.PowerSupplyStatusChanged += UwpPowerManager_PowerSupplyStatusChanged;
_powerSupplyStatusChangedSubscription.Disposable = Disposable.Create(() =>
UwpPowerManager.PowerSupplyStatusChanged -= UwpPowerManager_PowerSupplyStatusChanged);
}
Expand All @@ -169,6 +172,7 @@ public bool IsRemainingChargePercentChangedSubscribed
{
if (value)
{
UwpPowerManager.RemainingChargePercentChanged += UwpPowerManager_RemainingChargePercentChanged;
_remainingChargePercentChangedSubscription.Disposable = Disposable.Create(() =>
UwpPowerManager.RemainingChargePercentChanged -= UwpPowerManager_RemainingChargePercentChanged);
}
Expand All @@ -188,6 +192,7 @@ public bool IsRemainingDischargeTimeChangedSubscribed
{
if (value)
{
UwpPowerManager.RemainingDischargeTimeChanged += UwpPowerManager_RemainingDischargeTimeChanged;
_remainingDischargeTimeChangedSubscription.Disposable = Disposable.Create(() =>
UwpPowerManager.RemainingDischargeTimeChanged -= UwpPowerManager_RemainingDischargeTimeChanged);
}
Expand Down
5 changes: 5 additions & 0 deletions src/Uno.UI/LinkerDefinition.Wasm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@
<type fullname="Windows.Devices.Sensors.LightSensor" required="false">
<method name="DispatchReading" />
</type>
<type fullname="Windows.System.Power.PowerManager">
<method name="DispatchRemainingDischargeTimeChanged" />
<method name="DispatchRemainingChargePercentChanged" />
<method name="DispatchChargingChanged" />
</type>
<type fullname="Windows.Networking.Connectivity.NetworkInformation" required="false">
<method name="DispatchStatusChanged" />
</type>
Expand Down
69 changes: 69 additions & 0 deletions src/Uno.UI/ts/Windows/System/Power/PowerManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
declare class BatteryManager {
charging: boolean;
level: number;
dischargingTime: number;

addEventListener(
type: "chargingchange" | "dischargingtimechange" | "levelchange",
listener: (this: this, ev: Event) => any,
useCapture?: boolean): void;
}

interface Navigator {
Expand All @@ -12,10 +19,18 @@ namespace Windows.System.Power {
export class PowerManager {

private static battery: BatteryManager;
private static dispatchChargingChanged: () => number;
private static dispatchRemainingChargePercentChanged: () => number;
private static dispatchRemainingDischargeTimeChanged: () => number;

public static async initializeAsync(): Promise<string> {
if (!PowerManager.battery) {
PowerManager.battery = await navigator.getBattery();

// TODO: Subscribe only when requested
PowerManager.battery.addEventListener("chargingchange", PowerManager.onChargingChange);
PowerManager.battery.addEventListener("dischargingtimechange", PowerManager.onDischargingTimeChange);
PowerManager.battery.addEventListener("levelchange", PowerManager.onLevelChange);
}

return null;
Expand All @@ -28,5 +43,59 @@ namespace Windows.System.Power {

return "Idle";
}

public static getPowerSupplyStatus(): string {
if (PowerManager.battery) {
return PowerManager.battery.charging ? "Adequate" : "NotPresent";
}

return "NotPresent";
}

public static getRemainingChargePercent(): number {
if (PowerManager.battery) {
return PowerManager.battery.level;
}

return 1.0;
}

public static getRemainingDischargeTime(): number {
if (PowerManager.battery) {
const dischargingTime = PowerManager.battery.dischargingTime;
if (Number.isFinite(dischargingTime)) {
return dischargingTime;
}
}

return -1;
}

private static onChargingChange() {
if (!PowerManager.dispatchChargingChanged) {
PowerManager.dispatchChargingChanged =
(<any>Module).mono_bind_static_method(
"[Uno] Windows.System.Power.PowerManager:DispatchChargingChanged");
}
PowerManager.dispatchChargingChanged();
}

private static onDischargingTimeChange() {
if (!PowerManager.dispatchRemainingDischargeTimeChanged) {
PowerManager.dispatchRemainingDischargeTimeChanged =
(<any>Module).mono_bind_static_method(
"[Uno] Windows.System.Power.PowerManager:DispatchRemainingDischargeTimeChanged");
}
PowerManager.dispatchRemainingDischargeTimeChanged();
}

private static onLevelChange() {
if (!PowerManager.dispatchRemainingChargePercentChanged) {
PowerManager.dispatchRemainingChargePercentChanged =
(<any>Module).mono_bind_static_method(
"[Uno] Windows.System.Power.PowerManager:DispatchRemainingChargePercentChanged");
}
PowerManager.dispatchRemainingChargePercentChanged();
}
}
}
2 changes: 1 addition & 1 deletion src/Uno.UWP/System/Power/PowerManager.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public partial class PowerManager
private static readonly UIDevice _device;
private static readonly bool _isSimulator;

static PowerManager()
static partial void InitializePlatform()
{
_device = UIDevice.CurrentDevice;
_isSimulator = _device.Model?
Expand Down
84 changes: 80 additions & 4 deletions src/Uno.UWP/System/Power/PowerManager.wasm.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,98 @@
#nullable enable

using System;
using System.Threading.Tasks;
using Uno;
using Uno.Foundation;
using Uno.Foundation.Logging;

namespace Windows.System.Power;

public partial class PowerManager
{
private const string JsType = "Windows.System.Power.PowerManager";

[Preserve]
public static int DispatchChargingChanged()
{
RaiseBatteryStatusChanged();
RaisePowerSupplyStatusChanged();
return 0;
}

[Preserve]
public static int DispatchRemainingChargePercentChanged()
{
RaiseRemainingChargePercentChanged();
return 0;
}

[Preserve]
public static int DispatchRemainingDischargeTimeChanged()
{
RaiseRemainingDischargeTimeChanged();
return 0;
}

private static BatteryStatus GetBatteryStatus()
{
WebAssemblyRuntime.InvokeAsync($"{JsType}.initializeAsync()");
InitializeAsync(); // TODO

var batteryStatusString = WebAssemblyRuntime.InvokeJS($"{JsType}.getBatteryStatus()");
if (Enum.TryParse<BatteryStatus>(batteryStatusString, out var batteryStatus))
return Enum.TryParse<BatteryStatus>(batteryStatusString, out var batteryStatus) ?
batteryStatus : BatteryStatus.NotPresent;
}

private static PowerSupplyStatus GetPowerSupplyStatus()
{
InitializeAsync(); // TODO

var powerSupplyStatusString = WebAssemblyRuntime.InvokeJS($"{JsType}.getPowerSupplyStatus()");
return Enum.TryParse<PowerSupplyStatus>(powerSupplyStatusString, out var powerSupplyStatus) ?
powerSupplyStatus : PowerSupplyStatus.NotPresent;
}

private static int GetRemainingChargePercent()
{
InitializeAsync(); // TODO

var remainingChargeString = WebAssemblyRuntime.InvokeJS($"{JsType}.getRemainingChargePercent()");
if (double.TryParse(remainingChargeString, out var remainingCharge) &&
!double.IsNaN(remainingCharge))
{
return (int)(remainingCharge * 100);
}

return 100;
}

private static TimeSpan GetRemainingDischargeTime()
{
InitializeAsync(); // TODO

var remainingDischargeTimeString = WebAssemblyRuntime.InvokeJS($"{JsType}.getRemainingDischargeTime()");
if (double.TryParse(remainingDischargeTimeString, out var remainingDischargeTimeInSeconds) &&
!double.IsNaN(remainingDischargeTimeInSeconds) &&
remainingDischargeTimeInSeconds >= 0)
{
return TimeSpan.FromSeconds(remainingDischargeTimeInSeconds);
}

return TimeSpan.MaxValue;
}

private static async Task InitializeAsync()
{
try
{
await WebAssemblyRuntime.InvokeAsync($"{JsType}.initializeAsync()");
}
catch (Exception ex)
{
return batteryStatus;
if (typeof(PowerManager).Log().IsEnabled(LogLevel.Error))
{
typeof(PowerManager).Log().LogError("Could not initialize PowerManager", ex);
}
}
return BatteryStatus.NotPresent;
}
}

0 comments on commit 95a5a2b

Please sign in to comment.