feat(core): bettery save mode (#12996)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Introduced a battery save mode that can pause background sync and
processing to conserve energy.
* Battery save mode is automatically enabled when the app window loses
focus and disabled when the window regains focus or is interacted with.
  * Available in both web and desktop (Electron) versions.

* **Improvements**
* Added user activity detection to optimize background operations for
better battery efficiency.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
EYHN
2025-07-03 11:48:17 +08:00
committed by GitHub
parent 2ae3c3e2cd
commit b2bf591463
6 changed files with 102 additions and 0 deletions
@@ -159,6 +159,14 @@ export class IndexerSyncImpl implements IndexerSync {
this.remote = Object.values(this.peers.remotes).find(remote => !!remote);
}
enableBatterySaveMode() {
this.status.enableBatterySaveMode();
}
disableBatterySaveMode() {
this.status.disableBatterySaveMode();
}
start() {
if (this.abort) {
this.abort.abort(MANUALLY_STOP);
@@ -611,6 +619,10 @@ class IndexerSyncStatus {
currentJob: string | null = null;
errorMessage: string | null = null;
statusUpdatedSubject$ = new Subject<string | true>();
batterySaveMode: {
promise: Promise<void>;
resolve: () => void;
} | null = null;
state$ = new Observable<IndexerSyncState>(subscribe => {
const next = () => {
@@ -685,6 +697,9 @@ class IndexerSyncStatus {
}
async acceptJob(abort?: AbortSignal) {
if (this.batterySaveMode) {
await this.batterySaveMode.promise;
}
const job = await this.jobs.asyncPop(abort);
this.currentJob = job;
this.statusUpdatedSubject$.next(job);
@@ -709,6 +724,18 @@ class IndexerSyncStatus {
};
}
enableBatterySaveMode() {
if (this.batterySaveMode) {
return;
}
this.batterySaveMode = Promise.withResolvers();
}
disableBatterySaveMode() {
this.batterySaveMode?.resolve();
this.batterySaveMode = null;
}
reset() {
// reset all state, except prioritySettings
this.isReadonly = false;