Skip to content

Commit 48e3a2b

Browse files
committed
fix: Fixed various remaining bugs.
1 parent cb3254f commit 48e3a2b

File tree

7 files changed

+61
-26
lines changed

7 files changed

+61
-26
lines changed

lib/model/storage/online.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class OnlineStorage with Storage {
9595
@override
9696
Future<void> updateTotp(String uuid, Totp totp) async {
9797
CollectionReference? collection = _totpsCollection;
98-
await collection.doc(uuid).update(totp.toFirestore());
98+
await collection.doc(uuid).set(totp.toFirestore());
9999
}
100100

101101
@override

lib/model/totp/decrypted.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ class DecryptedTotp extends Totp {
5353
period: validity ?? Totp.kDefaultValidity,
5454
);
5555

56+
/// Generates a code using the [generator].
57+
String generateCode() => generator.value().toString().padLeft(digits ?? Totp.kDefaultDigits, '0');
58+
5659
@override
5760
List<Object?> get props => [...super.props, secret, label, issuer];
5861

lib/utils/utils.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ String generateRandomString([int length = 20]) {
2828
return String.fromCharCodes(Iterable.generate(length, (_) => chars.codeUnitAt(random.nextInt(chars.length))));
2929
}
3030

31-
/// Compares two [Uint8List]s by comparing 8 bytes at a time.ù
31+
/// Compares two [Uint8List]s by comparing 8 bytes at a time.
3232
/// Kudos to https://stackoverflow.com/a/70751501/3608831.
3333
bool memEquals(Uint8List bytes1, Uint8List bytes2) {
3434
if (identical(bytes1, bytes2)) {

lib/widgets/totp/code.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class _TotpCodeWidgetState extends TimeBasedTotpWidgetState<TotpCodeWidget> {
4141
if (!widget.totp.isDecrypted) {
4242
return '';
4343
}
44-
String code = (widget.totp as DecryptedTotp).generator.value().toString();
44+
String code = (widget.totp as DecryptedTotp).generateCode();
4545
StringBuffer buffer = StringBuffer();
4646
for (int i = 0; i < code.length; i++) {
4747
buffer.write(code[i]);

lib/widgets/totp/image.dart

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,7 @@ class _TotpCountdownImageWidgetState extends TimeBasedTotpWidgetState<TotpCountd
167167
if (((DateTime.now().millisecondsSinceEpoch ~/ 1000) ~/ this.validity).isEven) {
168168
changeColors();
169169
}
170-
Duration validity = _validity;
171-
animationController = AnimationController(
172-
vsync: this,
173-
duration: validity,
174-
upperBound: this.validity.toDouble(),
175-
)
176-
..addListener(() {
177-
setState(() {});
178-
})
179-
..forward(from: (validity - calculateExpirationDuration()).inMilliseconds / 1000);
170+
scheduleAnimation();
180171
}
181172

182173
@override
@@ -200,25 +191,53 @@ class _TotpCountdownImageWidgetState extends TimeBasedTotpWidgetState<TotpCountd
200191
),
201192
);
202193

194+
@override
195+
void didUpdateWidget(covariant TotpCountdownImageWidget oldWidget) {
196+
super.didUpdateWidget(oldWidget);
197+
if (oldWidget.totp.validity != widget.totp.validity) {
198+
cancelAnimation();
199+
scheduleAnimation();
200+
}
201+
}
202+
203203
@override
204204
void dispose() {
205-
animationController.dispose();
205+
cancelAnimation();
206206
super.dispose();
207207
}
208208

209209
@override
210210
void updateState({bool changeColors = true}) {
211211
if (mounted) {
212+
animationController.duration = _validity;
213+
animationController.forward(from: 0);
212214
setState(() {
213-
animationController.duration = _validity;
214-
animationController.forward(from: 0);
215215
if (changeColors) {
216216
this.changeColors();
217217
}
218218
});
219219
}
220220
}
221221

222+
/// Schedule the animation.
223+
void scheduleAnimation() {
224+
Duration validity = _validity;
225+
animationController = AnimationController(
226+
vsync: this,
227+
duration: validity,
228+
upperBound: this.validity.toDouble(),
229+
)
230+
..addListener(() {
231+
setState(() {});
232+
})
233+
..forward(from: (validity - calculateExpirationDuration()).inMilliseconds / 1000);
234+
}
235+
236+
/// Cancels the animation.
237+
void cancelAnimation() {
238+
animationController.dispose();
239+
}
240+
222241
/// Changes the colors.
223242
void changeColors() {
224243
Color? temporary = color;

lib/widgets/totp/time_based.dart

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,16 @@ abstract class TimeBasedTotpWidgetState<T extends TimeBasedTotpWidget> extends S
2626
@override
2727
void initState() {
2828
super.initState();
29-
_updateTimer = Timer(calculateExpirationDuration(), () {
30-
updateState();
31-
_updateTimer = Timer.periodic(Duration(seconds: validity), (_) => updateState());
32-
});
29+
_scheduleUpdates();
30+
}
31+
32+
@override
33+
void didUpdateWidget(covariant T oldWidget) {
34+
super.didUpdateWidget(oldWidget);
35+
if (oldWidget.totp.validity != widget.totp.validity) {
36+
_cancelUpdates();
37+
_scheduleUpdates();
38+
}
3339
}
3440

3541
@override
@@ -44,6 +50,14 @@ abstract class TimeBasedTotpWidgetState<T extends TimeBasedTotpWidget> extends S
4450
/// Triggered when the state should be updated.
4551
void updateState();
4652

53+
/// Schedule the updates.
54+
void _scheduleUpdates() {
55+
_updateTimer = Timer(calculateExpirationDuration(), () {
56+
updateState();
57+
_updateTimer = Timer.periodic(Duration(seconds: validity), (_) => updateState());
58+
});
59+
}
60+
4761
/// Cancels the updates.
4862
void _cancelUpdates() {
4963
_updateTimer?.cancel();

lib/widgets/totp/widget.dart

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'package:flutter/foundation.dart';
22
import 'package:flutter/material.dart';
33
import 'package:flutter/services.dart';
4-
import 'package:flutter_riverpod/flutter_riverpod.dart';
54
import 'package:open_authenticator/i18n/translations.g.dart';
65
import 'package:open_authenticator/model/totp/decrypted.dart';
76
import 'package:open_authenticator/model/totp/totp.dart';
@@ -12,7 +11,7 @@ import 'package:open_authenticator/widgets/totp/code.dart';
1211
import 'package:open_authenticator/widgets/totp/image.dart';
1312

1413
/// Allows to display TOTPs in a [ListView].
15-
class TotpWidget extends ConsumerWidget {
14+
class TotpWidget extends StatelessWidget {
1615
/// The TOTP instance.
1716
final Totp totp;
1817

@@ -51,7 +50,7 @@ class TotpWidget extends ConsumerWidget {
5150
});
5251

5352
@override
54-
Widget build(BuildContext context, WidgetRef ref) {
53+
Widget build(BuildContext context) {
5554
Widget result = Padding(
5655
padding: contentPadding,
5756
child: Row(
@@ -126,22 +125,22 @@ class TotpWidget extends ConsumerWidget {
126125
);
127126
return (currentPlatform.isMobile || kDebugMode)
128127
? InkWell(
129-
onLongPress: () => _showMobileActionsMenu(context, ref),
128+
onLongPress: () => _showMobileActionsMenu(context),
130129
child: result,
131130
)
132131
: result;
133132
}
134133

135134
/// Allows to copy the code to the clipboard.
136135
Future<void> _copyCode(BuildContext context) async {
137-
await Clipboard.setData(ClipboardData(text: (totp as DecryptedTotp).generator.value().toString()));
136+
await Clipboard.setData(ClipboardData(text: (totp as DecryptedTotp).generateCode()));
138137
if (context.mounted) {
139138
SnackBarIcon.showSuccessSnackBar(context, text: translations.totp.actions.copyConfirmation);
140139
}
141140
}
142141

143142
/// Triggered when the user long presses the widget on mobile.
144-
Future<void> _showMobileActionsMenu(BuildContext context, WidgetRef ref) async {
143+
Future<void> _showMobileActionsMenu(BuildContext context) async {
145144
if (!currentPlatform.isMobile && !kDebugMode) {
146145
Navigator.pushNamed(context, TotpPage.name);
147146
return;

0 commit comments

Comments
 (0)