feat(ui): PowerUse-Toggle im Usage-Monitor, Opt-in pro Liste
Der Toggle sitzt unter den Gauges im Usage-Monitor, weil "das restliche Fenster ausnutzen" eine Entscheidung ist, die man beim Blick auf das restliche Fenster trifft. Er speichert sofort per Read-modify-write, gleiche Disziplin wie SaveStagesAsync, damit er keine Felder ueberschreibt, die er nicht besitzt. Zwei Stellen, die das Opt-in still ausgeschaltet haetten: - WorkerHub.UpdateListConfig loescht die Config-Zeile, wenn alle Felder leer sind. PowerUseAllowed muss in diese Leer-Pruefung, sonst verschwindet das Opt-in sofort wieder, wenn es das einzige gesetzte Feld ist. - SettingsModalViewModel baut das AppSettingsDto positional neu auf. Ohne Round-trip haette jedes Speichern der Settings PowerUseEnabled auf den Record-Default false zurueckgesetzt. Gleiches Muster wie _throttleStages. Das Handoff-Budget ist als Spinner in Settings -> General editierbar, weil es auch fuer normale (interaktive) Handler-Runs gilt und nicht an PowerUse haengt. Das Addendum selbst ist ueber Settings -> Files anpassbar.
This commit is contained in:
@@ -100,6 +100,45 @@ public sealed partial class UsageMonitorModalViewModel : ViewModelBase
|
||||
[ObservableProperty]
|
||||
private IReadOnlyList<UsageGaugeRowViewModel> _gaugeRows = Array.Empty<UsageGaugeRowViewModel>();
|
||||
|
||||
/// <summary>
|
||||
/// PowerUse master switch. It lives here rather than in Settings because turning it on is a
|
||||
/// "spend the rest of the window" decision, made while looking at how much window is left.
|
||||
/// On its own it changes nothing — a list-handler run only goes unattended when its LIST also
|
||||
/// opted in (list settings → PowerUse), so this can stay on without affecting other lists.
|
||||
/// </summary>
|
||||
[ObservableProperty] private bool _powerUseEnabled;
|
||||
|
||||
// Set while LoadAsync writes the stored value in, so seeding the property doesn't immediately
|
||||
// write it straight back to the worker.
|
||||
private bool _loadingPowerUse;
|
||||
|
||||
partial void OnPowerUseEnabledChanged(bool value)
|
||||
{
|
||||
if (_loadingPowerUse) return;
|
||||
_ = SavePowerUseAsync(value);
|
||||
}
|
||||
|
||||
/// Read-modify-write, same discipline as SaveStagesAsync: never clobber a field this modal
|
||||
/// doesn't own.
|
||||
private async Task SavePowerUseAsync(bool value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var settings = await _worker.GetAppSettingsAsync();
|
||||
if (settings is null)
|
||||
{
|
||||
ErrorReported?.Invoke(Loc.T("vm.usageMonitor.powerUseSaveFailed", Loc.T("vm.settingsModal.workerOffline")));
|
||||
return;
|
||||
}
|
||||
|
||||
await _worker.UpdateAppSettingsAsync(settings with { PowerUseEnabled = value });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorReported?.Invoke(Loc.T("vm.usageMonitor.powerUseSaveFailed", ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsStale => Snapshot?.IsStale == true;
|
||||
public string? LastError => Snapshot?.LastError;
|
||||
public bool IsGateBlocked => Snapshot?.IsGateBlocked == true;
|
||||
@@ -148,6 +187,15 @@ public sealed partial class UsageMonitorModalViewModel : ViewModelBase
|
||||
Snapshot = snapshot;
|
||||
_worker.UsageUpdatedEvent -= OnUsageUpdated;
|
||||
_worker.UsageUpdatedEvent += OnUsageUpdated;
|
||||
|
||||
var settings = await _worker.GetAppSettingsAsync();
|
||||
if (settings is not null)
|
||||
{
|
||||
_loadingPowerUse = true;
|
||||
try { PowerUseEnabled = settings.PowerUseEnabled; }
|
||||
finally { _loadingPowerUse = false; }
|
||||
}
|
||||
|
||||
ApplyPresetRange(SelectedPresetDays);
|
||||
await LoadUsageDataAsync();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user