Skip to content

Commit 9ced087

Browse files
committed
chore: Various fixes and improvements.
1 parent 8b67254 commit 9ced087

27 files changed

Lines changed: 125 additions & 119 deletions

lib/i18n/de/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@
137137
"title": "Sicherungen verwalten",
138138
"subtitle": {
139139
"zero": "Sie haben keine Sicherung gespeichert.",
140-
"one": "Sie haben derzeit $n Sicherung gespeichert.",
141-
"other": "Sie haben derzeit $n Sicherungen gespeichert."
140+
"one(rich)": "Sie haben derzeit $backups Sicherung gespeichert.",
141+
"more(rich)": "Sie haben derzeit $backups Sicherungen gespeichert."
142142
},
143143
"backupsDialogTitle": "Sicherungen verwalten",
144144
"restoreBackupPasswordDialog": {

lib/i18n/en/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@
137137
"title": "Manage backups",
138138
"subtitle": {
139139
"zero": "You do not have any backup stored.",
140-
"one": "You currently have $n backup stored.",
141-
"other": "You currently have $n backups stored."
140+
"one(rich)": "You currently have $backups backup stored.",
141+
"more(rich)": "You currently have $backups backups stored."
142142
},
143143
"backupsDialogTitle": "Manage backups",
144144
"restoreBackupPasswordDialog": {

lib/i18n/fr/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@
137137
"title": "Gestion des sauvegardes",
138138
"subtitle": {
139139
"zero": "Vous n'avez aucune sauvegarde.",
140-
"one": "Vous avez actuellement $n sauvegarde.",
141-
"other": "Vous avez actuellement $n sauvegardes."
140+
"one(rich)": "Vous avez actuellement $backups sauvegarde.",
141+
"more(rich)": "Vous avez actuellement $backups sauvegardes."
142142
},
143143
"backupsDialogTitle": "Gestion des sauvegardes",
144144
"restoreBackupPasswordDialog": {

lib/i18n/it/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@
137137
"title": "Gestisci backup",
138138
"subtitle": {
139139
"zero": "Non hai backup memorizzati.",
140-
"one": "Attualmente hai $n backup memorizzato.",
141-
"other": "Attualmente hai $n backup memorizzati."
140+
"one(rich)": "Attualmente hai $backups backup memorizzato.",
141+
"more(rich)": "Attualmente hai $backups backup memorizzati."
142142
},
143143
"backupsDialogTitle": "Gestisci backup",
144144
"restoreBackupPasswordDialog": {

lib/i18n/pt/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@
137137
"title": "Gerenciar backups",
138138
"subtitle": {
139139
"zero": "Você não possui nenhum backup armazenado.",
140-
"one": "Atualmente, você possui $n backup armazenado.",
141-
"other": "Atualmente, você possui $n backups armazenados."
140+
"one(rich)": "Atualmente, você possui $backups backup armazenado.",
141+
"more(rich)": "Atualmente, você possui $backups backups armazenados."
142142
},
143143
"backupsDialogTitle": "Gerenciar backups",
144144
"restoreBackupPasswordDialog": {

lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ class _RouteWidgetState extends ConsumerState<_RouteWidget> {
269269
if (previous == next) {
270270
return;
271271
}
272-
if (next == .invalidSession) {
272+
if (next is SessionRefreshStateInvalidSession) {
273273
WidgetsBinding.instance.addPostFrameCallback((_) => handleInvalidSession());
274274
}
275275
},

lib/model/app_unlock/methods/method.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ part 'master_password.dart';
1919
part 'none.dart';
2020

2121
/// The app unlock method provider.
22-
final appUnlockMethodProvider = Provider.autoDispose.family<AppUnlockMethod?, String>(
22+
final appUnlockMethodProvider = Provider.family<AppUnlockMethod?, String>(
2323
(ref, id) => switch (id) {
2424
LocalAuthenticationAppUnlockMethod.kMethodId => LocalAuthenticationAppUnlockMethod._(ref: ref),
2525
MasterPasswordAppUnlockMethod.kMethodId => MasterPasswordAppUnlockMethod._(ref: ref),

lib/model/backend/authentication/providers/provider.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ sealed class AuthenticationProvider {
103103
}
104104
User? user = await _ref.read(userProvider.future);
105105
SessionRefreshState sessionRefreshState = _ref.read(sessionRefreshManagerProvider);
106-
if (user == null || sessionRefreshState == .invalidSession) {
106+
if (user == null || sessionRefreshState is SessionRefreshStateInvalidSession) {
107107
Result<ProviderLoginResponse> response = await _ref
108108
.read(backendClientProvider.notifier)
109109
.sendHttpRequest(

lib/model/backend/authentication/session.dart

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,18 +100,24 @@ class SessionRefreshManager extends Notifier<SessionRefreshState> {
100100
SessionRefreshState build() {
101101
ref.listen(storedSessionProvider, (_, _) {
102102
if (ref.mounted) {
103-
state = .idle;
103+
state = const SessionRefreshStateIdle();
104104
}
105105
});
106-
return .idle;
106+
return const SessionRefreshStateIdle();
107107
}
108108

109109
/// Refreshes the session.
110110
Future<Result> refresh({Session? session}) async {
111-
if (!ref.mounted || state == .inProgress || state == .invalidSession) {
112-
return const ResultCancelled();
111+
Result result = const ResultCancelled();
112+
if (!ref.mounted || state is SessionRefreshStateInvalidSession) {
113+
return result;
114+
}
115+
if (state is SessionRefreshStateInProgress) {
116+
return await (state as SessionRefreshStateInProgress)._pendingRefresh.future;
113117
}
114-
state = .inProgress;
118+
119+
Completer<Result>? pendingRefresh = Completer();
120+
state = SessionRefreshStateInProgress(pendingRefresh: pendingRefresh);
115121
try {
116122
BackendClient backend = await ref.read(backendClientProvider.notifier);
117123
Result<Session> result = await _sendRefreshRequest(backend, session: session);
@@ -122,11 +128,10 @@ class SessionRefreshManager extends Notifier<SessionRefreshState> {
122128
return result;
123129
}
124130
await ref.read(storedSessionProvider.notifier).storeAndUse(result.value);
125-
if (!ref.mounted) {
126-
return const ResultCancelled();
131+
if (ref.mounted) {
132+
state = const SessionRefreshStateSuccess();
133+
result = const ResultSuccess();
127134
}
128-
state = .success;
129-
return const ResultSuccess();
130135
} catch (ex, stackTrace) {
131136
List<String> invalidSessionCodes = [
132137
InvalidPayloadError.kErrorCode,
@@ -135,13 +140,15 @@ class SessionRefreshManager extends Notifier<SessionRefreshState> {
135140
ExpiredSessionError.kErrorCode,
136141
];
137142
if (ex is BackendRequestError && invalidSessionCodes.contains(ex.code) && ref.mounted) {
138-
state = .invalidSession;
143+
state = const SessionRefreshStateInvalidSession();
139144
}
140-
return ResultError(
145+
result = ResultError(
141146
exception: ex,
142147
stackTrace: stackTrace,
143148
);
144149
}
150+
pendingRefresh.complete(result);
151+
return result;
145152
}
146153

147154
/// Sends a refresh request.
@@ -177,16 +184,36 @@ class NoSessionException extends LocalizableException {
177184
}
178185

179186
/// The session refresh state.
180-
enum SessionRefreshState {
181-
/// The session refresh state is idle.
182-
idle,
187+
sealed class SessionRefreshState {
188+
/// Creates a new session refresh state instance.
189+
const SessionRefreshState();
190+
}
183191

184-
/// The session refresh state is in progress.
185-
inProgress,
192+
/// The session refresh state is idle.
193+
class SessionRefreshStateIdle extends SessionRefreshState {
194+
/// Creates a new idle session refresh state instance.
195+
const SessionRefreshStateIdle();
196+
}
197+
198+
/// The session refresh state is in progress.
199+
class SessionRefreshStateInProgress extends SessionRefreshState {
200+
/// The pending refresh completer.
201+
final Completer<Result> _pendingRefresh;
186202

187-
/// The session refresh state is success.
188-
success,
203+
/// Creates a new in progress session refresh state instance.
204+
SessionRefreshStateInProgress({
205+
required Completer<Result> pendingRefresh,
206+
}) : _pendingRefresh = pendingRefresh;
207+
}
208+
209+
/// The session refresh state is success.
210+
class SessionRefreshStateSuccess extends SessionRefreshState {
211+
/// Creates a new success session refresh state instance.
212+
const SessionRefreshStateSuccess();
213+
}
189214

190-
/// The session refresh state is invalid.
191-
invalidSession,
215+
/// The session refresh state is invalid.
216+
class SessionRefreshStateInvalidSession extends SessionRefreshState {
217+
/// Creates a new invalid session refresh state instance.
218+
const SessionRefreshStateInvalidSession();
192219
}

lib/model/backend/backend.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class BackendClient extends AsyncNotifier<Map<String, String>> {
6969

7070
Map<String, String> headers = await _writeAppClientIdIfNeeded();
7171
if (request.needsAuthorization) {
72-
if (ref.read(sessionRefreshManagerProvider) == .invalidSession) {
72+
if (ref.read(sessionRefreshManagerProvider) is SessionRefreshStateInvalidSession) {
7373
throw InvalidSessionException();
7474
}
7575
session ??= await ref.read(storedSessionProvider.future);

0 commit comments

Comments
 (0)