fix some smaller issues

This commit is contained in:
otsmr 2026-07-15 20:20:02 +02:00
parent 2a4574ef36
commit 4588c9995d
8 changed files with 35 additions and 30 deletions

View file

@ -15,7 +15,6 @@ import 'package:twonly/src/model/json/onboarding_state.model.dart';
import 'package:twonly/src/providers/routing.provider.dart';
import 'package:twonly/src/providers/settings.provider.dart';
import 'package:twonly/src/services/intent/links.intent.dart';
import 'package:twonly/src/services/passwordless_recovery.service.dart';
import 'package:twonly/src/utils/keyvalue.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/pow.dart';
@ -182,11 +181,6 @@ class _AppMainWidgetState extends State<AppMainWidget> {
context,
handleShareLink,
);
_emailTokenSub = PasswordlessRecoveryService.onEmailTokenReceived.stream
.listen((token) {
routerProvider.go(Routes.recoverPasswordless, extra: token);
});
}
Future<void> initAsync() async {

View file

@ -195,8 +195,12 @@ class TwonlySafeBackup {
factory TwonlySafeBackup.fromJson(Map<String, dynamic> json) =>
_$TwonlySafeBackupFromJson(json);
@JsonKey(defaultValue: 0)
int lastBackupSize = 0;
@JsonKey(defaultValue: LastBackupUploadState.none)
LastBackupUploadState backupUploadState = LastBackupUploadState.none;
DateTime? lastBackupDone;
List<int> backupId;
List<int> encryptionKey;
@ -216,6 +220,7 @@ class PasswordLessRecovery {
// <--
// Data shared with trusted friends
@JsonKey(defaultValue: 2)
int threshold;
// Trusted friends are able to brute-force the pin -> Server delets after X tries
List<int>? pinSeed;

View file

@ -202,11 +202,13 @@ TwonlySafeBackup _$TwonlySafeBackupFromJson(Map<String, dynamic> json) =>
.map((e) => (e as num).toInt())
.toList(),
)
..lastBackupSize = (json['lastBackupSize'] as num).toInt()
..backupUploadState = $enumDecode(
_$LastBackupUploadStateEnumMap,
json['backupUploadState'],
)
..lastBackupSize = (json['lastBackupSize'] as num?)?.toInt() ?? 0
..backupUploadState =
$enumDecodeNullable(
_$LastBackupUploadStateEnumMap,
json['backupUploadState'],
) ??
LastBackupUploadState.none
..lastBackupDone = json['lastBackupDone'] == null
? null
: DateTime.parse(json['lastBackupDone'] as String);
@ -230,7 +232,7 @@ const _$LastBackupUploadStateEnumMap = {
PasswordLessRecovery _$PasswordLessRecoveryFromJson(
Map<String, dynamic> json,
) => PasswordLessRecovery((json['threshold'] as num).toInt())
) => PasswordLessRecovery((json['threshold'] as num?)?.toInt() ?? 2)
..email = json['email'] as String?
..pinSeed = (json['pinSeed'] as List<dynamic>?)
?.map((e) => (e as num).toInt())

View file

@ -36,6 +36,8 @@ class PasswordlessRecoveryService {
static final StreamController<String> onEmailTokenReceived =
StreamController<String>.broadcast();
static String? lastEmailToken;
static String linkPrefix = 'https://me.twonly.eu/r/#';
static final Set<String> _handledNotificationIds = {};
@ -48,6 +50,7 @@ class PasswordlessRecoveryService {
final parts = fragment.split('/');
if (parts.length < 2) {
if (fragment.isNotEmpty) {
lastEmailToken = fragment;
onEmailTokenReceived.add(fragment);
}
return;

View file

@ -245,7 +245,7 @@ class EmojiAnimationComp extends StatelessWidget {
return Lottie.asset(
'assets/animated_icons/${animatedIcons[emoji]}',
repeat: repeat,
renderCache: RenderCache.raster,
renderCache: RenderCache.drawingCommands,
);
} else if (isOneEmoji(emoji)) {
return Text(

View file

@ -60,26 +60,21 @@ class _RecoverPasswordlessState extends State<RecoverPasswordless> {
@override
void initState() {
super.initState();
_secondFactorController.text = widget.initialEmailToken ?? '';
final token =
widget.initialEmailToken ?? PasswordlessRecoveryService.lastEmailToken;
_secondFactorController.text = token ?? '';
_emailTokenSubscription = PasswordlessRecoveryService
.onEmailTokenReceived
.stream
.listen((token) async {
if (mounted) {
final state = _onboardingState;
if (state != null && !state.emailRecoveryRequested) {
state.emailRecoveryRequested = true;
await KeyValueStore.update<OnboardingState>(
key: KeyValueKeys.onboardingState,
update: (s) => s.emailRecoveryRequested = true,
);
}
setState(() {
_secondFactorController.text = token;
});
}
});
_initAsync();
_initAsync(token);
}
@override
@ -90,14 +85,14 @@ class _RecoverPasswordlessState extends State<RecoverPasswordless> {
super.dispose();
}
Future<void> _initAsync() async {
Future<void> _initAsync(String? initialToken) async {
try {
// 1. Load OnboardingState
final state = await KeyValueStore.getModel<OnboardingState>(
KeyValueKeys.onboardingState,
);
if (widget.initialEmailToken != null && !state.emailRecoveryRequested) {
if (initialToken != null && !state.emailRecoveryRequested) {
state.emailRecoveryRequested = true;
await KeyValueStore.update<OnboardingState>(
key: KeyValueKeys.onboardingState,

View file

@ -75,10 +75,16 @@ class _ChatReactionSelectionView extends State<ChatReactionSelectionView> {
? context.color.primary.withAlpha(150)
: context.color.surface,
child: Center(
child: Text(
emoji,
style: const TextStyle(fontSize: 32),
),
child: isSelected
? SizedBox(
width: 40,
height: 40,
child: EmojiAnimationComp(emoji: emoji),
)
: Text(
emoji,
style: const TextStyle(fontSize: 32),
),
),
),
);

View file

@ -1266,7 +1266,7 @@ packages:
path: "dependencies/lottie"
relative: true
source: path
version: "3.3.2"
version: "3.5.1"
markdown:
dependency: transitive
description: