Skip to content

Commit d55da5f

Browse files
authored
prerelease: cost-cutting fixes #5497 #5498 #5499 (#5529)
## Prerelease: 3 Verified Cost-Cutting Fixes Combines PRs #5497, #5498, #5499 into a single merge-ready branch. All independently verified (PR #5505 — 16/16 tests + physical device E2E on Pixel 7a). ### Merge Order (preserved in branch) 1. **PR #5498** — Fix translate debounce: temporal window instead of inert segment-ID tracking 2. **PR #5497** — fix(app): break token refresh infinite retry loop 3. **PR #5499** — fix(backend-listen): WebSocket auth sends close frame instead of crashing handshake ### Verification Evidence - Combined verification: #5505 - 16/16 unit tests pass (all 3 PRs) - Physical device E2E (Pixel 7a + Omi BLE, LOCAL_DEVELOPMENT=false): 30s + 5min podcast tests PASS - Re-verification after auth fix (split WS auth): #5505 (comment) - Physical device E2E evidence: #5505 (comment) ### Ancestry Check All 3 sub-PR HEADs confirmed as ancestors of this branch: - `fix/translate-debounce-5444` (c8a1406) ✓ - `fix/token-refresh-infinite-retry-5448` (c937df7) ✓ - `fix/ws-auth-handshake-5447` (35c0b5c) ✓ ### For @mon This PR is ready to merge. Regular merge (no squash).
2 parents b56280f + f378dcc commit d55da5f

File tree

10 files changed

+1053
-144
lines changed

10 files changed

+1053
-144
lines changed

app/lib/providers/auth_provider.dart

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ class AuthenticationProvider extends BaseProvider {
5050
});
5151
_auth.idTokenChanges().distinct((p, n) => p?.uid == n?.uid).listen((User? user) async {
5252
if (user == null) {
53-
Logger.debug('User is currently signed out or the token has been revoked! ${user == null}');
54-
// Don't clear cached token - allows fallback for dev builds
55-
// SharedPreferencesUtil().authToken = '';
56-
// authToken = null;
53+
Logger.debug('User is currently signed out or the token has been revoked!');
54+
SharedPreferencesUtil().authToken = '';
55+
SharedPreferencesUtil().tokenExpirationTime = 0;
56+
authToken = null;
5757
} else {
5858
Logger.debug('User is signed in at ${DateTime.now()} with user ${user.uid}');
5959
try {
@@ -72,20 +72,7 @@ class AuthenticationProvider extends BaseProvider {
7272
}
7373

7474
bool isSignedIn() {
75-
// Check Firebase SDK first
76-
if (_auth.currentUser != null && !_auth.currentUser!.isAnonymous) {
77-
return true;
78-
}
79-
// Fallback: check cached credentials (for dev builds where Keychain doesn't persist)
80-
// This matches the Swift desktop app behavior
81-
final cachedUid = SharedPreferencesUtil().uid;
82-
final cachedToken = SharedPreferencesUtil().authToken;
83-
print('DEBUG AuthProvider.isSignedIn: cachedUid="${cachedUid}", tokenLength=${cachedToken.length}');
84-
if (cachedUid.isNotEmpty && cachedToken.isNotEmpty) {
85-
print('DEBUG AuthProvider: Using cached credentials fallback - uid=$cachedUid');
86-
return true;
87-
}
88-
return false;
75+
return _auth.currentUser != null && !_auth.currentUser!.isAnonymous;
8976
}
9077

9178
void setLoading(bool value) {

app/lib/providers/capture_provider.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'package:permission_handler/permission_handler.dart';
1616
import 'package:omi/backend/http/api/conversations.dart';
1717
import 'package:omi/backend/http/api/users.dart';
1818
import 'package:omi/backend/preferences.dart';
19+
import 'package:omi/services/auth_service.dart';
1920
import 'package:omi/backend/schema/bt_device/bt_device.dart';
2021
import 'package:omi/backend/schema/conversation.dart';
2122
import 'package:omi/backend/schema/geolocation.dart';
@@ -1338,6 +1339,12 @@ class CaptureProvider extends ChangeNotifier
13381339
return;
13391340
}
13401341

1342+
if (!AuthService.instance.isSignedIn()) {
1343+
Logger.debug("[Provider] keep alive - user not signed in, cancelling reconnect");
1344+
t.cancel();
1345+
return;
1346+
}
1347+
13411348
if (_recordingDevice != null) {
13421349
BleAudioCodec codec = await _getAudioCodec(_recordingDevice!.id);
13431350
await _initiateWebsocket(audioCodec: codec, source: _getConversationSourceFromDevice());

app/lib/services/auth_service.dart

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,22 @@ class AuthService {
169169
}
170170

171171
Future<void> signOut() async {
172+
_clearCachedAuth();
172173
await FirebaseAuth.instance.signOut();
173174
}
174175

176+
void _clearCachedAuth() {
177+
SharedPreferencesUtil().authToken = '';
178+
SharedPreferencesUtil().tokenExpirationTime = 0;
179+
}
180+
175181
Future<String?> getIdToken() async {
176182
try {
183+
if (FirebaseAuth.instance.currentUser == null) {
184+
Logger.debug('getIdToken: currentUser is null, clearing cached token');
185+
_clearCachedAuth();
186+
return null;
187+
}
177188
IdTokenResult? newToken = await FirebaseAuth.instance.currentUser?.getIdTokenResult(true);
178189
if (newToken?.token != null) {
179190
var user = FirebaseAuth.instance.currentUser!;
@@ -194,16 +205,12 @@ class AuthService {
194205
}
195206
return newToken?.token;
196207
}
197-
// Fallback: use cached token if Firebase has no user (for dev builds)
198-
final cachedToken = SharedPreferencesUtil().authToken;
199-
if (cachedToken.isNotEmpty) {
200-
print('DEBUG AuthService.getIdToken: Using cached token fallback');
201-
return cachedToken;
202-
}
208+
Logger.debug('getIdToken: token refresh returned null');
203209
return null;
204210
} catch (e) {
205-
Logger.debug(e.toString());
206-
return SharedPreferencesUtil().authToken;
211+
Logger.debug('getIdToken: token refresh failed: $e');
212+
_clearCachedAuth();
213+
return null;
207214
}
208215
}
209216

app/test.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@ flutter test test/unit/audio_player_utils_test.dart
5151
flutter test test/unit/env_test.dart
5252
flutter test test/unit/testflight_preferences_test.dart
5353
flutter test test/unit/multipart_401_retry_test.dart
54+
flutter test test/unit/token_refresh_loop_test.dart

0 commit comments

Comments
 (0)