[auth] Reduce progress bar refresh rate to lower CPU usage (#4517)
## Description Related https://github.com/ente-io/ente/issues/2003#issuecomment-2563380828 ## Tests
This commit is contained in:
@@ -1,58 +1,58 @@
|
||||
import 'package:ente_auth/services/preference_service.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ente_auth/theme/ente_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
||||
class CodeTimerProgressCache {
|
||||
static final Map<int, CodeTimerProgress> _cache = {};
|
||||
|
||||
static CodeTimerProgress getCachedWidget(int period) {
|
||||
if (!_cache.containsKey(period)) {
|
||||
_cache[period] = CodeTimerProgress(period: period);
|
||||
}
|
||||
return _cache[period]!;
|
||||
}
|
||||
}
|
||||
|
||||
class CodeTimerProgress extends StatefulWidget {
|
||||
final int period;
|
||||
|
||||
final bool isCompactMode;
|
||||
const CodeTimerProgress({
|
||||
super.key,
|
||||
required this.period,
|
||||
this.isCompactMode = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<CodeTimerProgress> createState() => _CodeTimerProgressState();
|
||||
}
|
||||
|
||||
class _CodeTimerProgressState extends State<CodeTimerProgress>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final Ticker _ticker;
|
||||
class _CodeTimerProgressState extends State<CodeTimerProgress> {
|
||||
late final Timer _timer;
|
||||
late final ValueNotifier<double> _progress;
|
||||
late final int _microSecondsInPeriod;
|
||||
late bool _isCompactMode=false;
|
||||
late final int _periodInMicros;
|
||||
|
||||
// Cache the start time to avoid repeated system calls
|
||||
late final int _startMicros;
|
||||
|
||||
// Reduce update frequency
|
||||
final int _updateIntervalMs =
|
||||
(Platform.isAndroid || Platform.isIOS) ? 16 : 500; // approximately 60 FPS
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_microSecondsInPeriod = widget.period * 1000000;
|
||||
_periodInMicros = widget.period * 1000000;
|
||||
_progress = ValueNotifier<double>(0.0);
|
||||
_ticker = createTicker(_updateTimeRemaining);
|
||||
_ticker.start();
|
||||
_isCompactMode = PreferenceService.instance.isCompactMode();
|
||||
_updateTimeRemaining(Duration.zero);
|
||||
_startMicros = DateTime.now().microsecondsSinceEpoch;
|
||||
|
||||
// Use a Timer instead of a Ticker
|
||||
_timer = Timer.periodic(Duration(milliseconds: _updateIntervalMs), (timer) {
|
||||
final now = DateTime.now().microsecondsSinceEpoch;
|
||||
_updateTimeRemaining(now);
|
||||
});
|
||||
}
|
||||
|
||||
void _updateTimeRemaining(Duration elapsed) {
|
||||
int timeRemaining = _microSecondsInPeriod -
|
||||
(DateTime.now().microsecondsSinceEpoch % _microSecondsInPeriod);
|
||||
_progress.value = timeRemaining / _microSecondsInPeriod;
|
||||
void _updateTimeRemaining(int currentMicros) {
|
||||
// More efficient time calculation using modulo
|
||||
final elapsed = (currentMicros - _startMicros) % _periodInMicros;
|
||||
final timeRemaining = _periodInMicros - elapsed;
|
||||
_progress.value = timeRemaining / _periodInMicros;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_ticker.dispose();
|
||||
_timer.cancel();
|
||||
_progress.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
@@ -60,18 +60,19 @@ class _CodeTimerProgressState extends State<CodeTimerProgress>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: _isCompactMode ?1:3,
|
||||
height: widget.isCompactMode ? 1 : 3,
|
||||
child: ValueListenableBuilder<double>(
|
||||
valueListenable: _progress,
|
||||
builder: (context, progress, _) {
|
||||
return CustomPaint(
|
||||
key: Key(progress.toString()), // Add key here
|
||||
painter: _ProgressPainter(
|
||||
progress: progress,
|
||||
color: progress > 0.4
|
||||
? getEnteColorScheme(context).primary700
|
||||
: Colors.orange,
|
||||
),
|
||||
size: Size.infinite,
|
||||
size: const Size.fromHeight(double.infinity),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -83,7 +84,10 @@ class _ProgressPainter extends CustomPainter {
|
||||
final double progress;
|
||||
final Color color;
|
||||
|
||||
_ProgressPainter({required this.progress, required this.color});
|
||||
const _ProgressPainter({
|
||||
required this.progress,
|
||||
required this.color,
|
||||
});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
|
||||
@@ -146,8 +146,10 @@ class _CodeWidgetState extends State<CodeWidget> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (widget.code.type.isTOTPCompatible)
|
||||
CodeTimerProgressCache.getCachedWidget(
|
||||
widget.code.period,
|
||||
CodeTimerProgress(
|
||||
key: ValueKey('period_${widget.code.period}'),
|
||||
period: widget.code.period,
|
||||
isCompactMode: widget.isCompactMode,
|
||||
),
|
||||
widget.isCompactMode
|
||||
? const SizedBox(height: 4)
|
||||
|
||||
@@ -429,6 +429,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.ente.auth.mac;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
@@ -42,10 +42,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: app_links
|
||||
sha256: ad1a6d598e7e39b46a34f746f9a8b011ee147e4c275d407fa457e7a62f84dd99
|
||||
sha256: "433df2e61b10519407475d7f69e470789d23d593f28224c38ba1068597be7950"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.2"
|
||||
version: "6.3.3"
|
||||
app_links_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -528,10 +528,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_inappwebview
|
||||
sha256: "93cfcca02bdda4b26cd700cf70d9ddba09d8348e3e8f2857638c23ed23a4fcb4"
|
||||
sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "6.1.5"
|
||||
flutter_inappwebview_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -584,10 +584,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview_windows
|
||||
sha256: "95ebc65aecfa63b2084c822aec6ba0545f0a0afaa3899f2c752ec96c09108db5"
|
||||
sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0+2"
|
||||
version: "0.6.0"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -985,10 +985,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
macros:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1655,10 +1655,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3"
|
||||
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
version: "6.3.1"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1668,7 +1668,7 @@ packages:
|
||||
source: hosted
|
||||
version: "6.3.11"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: ente_auth
|
||||
description: ente two-factor authenticator
|
||||
version: 4.2.0+420
|
||||
version: 4.2.1+421
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
|
||||
Reference in New Issue
Block a user