Skip to content

Commit bc4f0d2

Browse files
Merge pull request #342 from Hash-Studios/akshay/3.0.8
feat: v3.0.8
2 parents fe99654 + 5302865 commit bc4f0d2

19 files changed

Lines changed: 1644 additions & 1002 deletions

File tree

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
## Changelog
22

3+
### v3.0.8
4+
- Refined the edit profile flow and redesigned the profile completeness widget
5+
- Applied minor profile UI polish and layout rework
6+
- Additional Sentry fixes and test stability improvements
7+
- Version and build number update for release
8+
9+
### v3.0.7
10+
- Added user blocking, with follow-up fixes for notification auth, cooldowns, and review feedback
11+
- Revamped the collections page, personalised feed editor, AI generation screen, streak UI, and bottom bar sizing
12+
- Grouped notifications and improved in-app notification behaviour
13+
- Added wallpaper reporting and migrated wall/setup view tracking from GitHub-backed data to Firestore
14+
- Fixed Wall of the Day generation, profile refresh, and edit profile reliability
15+
- Reworked the wallpaper detail sheet with liquid-glass styling, richer color handling, better author/date presentation, and tap animations
16+
- Improved startup performance and added an email export utility
17+
- iOS release stability fixes, including build/review compliance updates, Firebase/plugin updates, media host support, and app icon refresh
18+
- Website refresh plus Kotlin, CI, pigeon, and formatting fixes for release stability
19+
320
### v3.0.6
421
- Version and build number update for release
522

lib/auth/google_auth.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,13 @@ class GoogleAuth {
196196

197197
bool _isSignInCancelled(Object error) {
198198
if (error is GoogleSignInException) {
199-
return error.code == GoogleSignInExceptionCode.canceled;
199+
return error.code == GoogleSignInExceptionCode.canceled || error.code == GoogleSignInExceptionCode.unknownError;
200200
}
201201
final String message = error.toString().toLowerCase();
202-
return message.contains('user canceled') || message.contains('cancelled');
202+
return message.contains('user canceled') ||
203+
message.contains('cancelled') ||
204+
message.contains('no credential') ||
205+
message.contains('no credentials available');
203206
}
204207

205208
Future<bool> signOutGoogle() async {

lib/core/constants/app_constants.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import 'package:Prism/auth/userModel.dart';
55
const String defaultProfilePhotoUrl =
66
'https://firebasestorage.googleapis.com/v0/b/prism-wallpapers.appspot.com/o/Replacement%20Thumbnails%2Fpost%20bg.png?alt=media&token=d708b5e3-a7ee-421b-beae-3b10946678c4';
77

8-
const String currentAppVersion = '3.0.7';
9-
const String currentAppVersionCode = '330';
8+
const String currentAppVersion = '3.0.8';
9+
const String currentAppVersionCode = '331';
1010
const String defaultObsoleteAppVersion = '2.6.0';
1111

1212
const String defaultBannerText = 'Join our Telegram';

lib/core/firestore/firestore_tracked_client.dart

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:async';
2+
import 'dart:math' as math;
23

34
import 'package:Prism/core/firestore/firestore_client.dart';
45
import 'package:Prism/core/firestore/firestore_error.dart';
@@ -7,6 +8,10 @@ import 'package:Prism/core/firestore/firestore_telemetry.dart';
78
import 'package:Prism/logger/logger.dart';
89
import 'package:cloud_firestore/cloud_firestore.dart';
910

11+
const _transientFirestoreCodes = {'unavailable', 'deadline-exceeded', 'internal', 'resource-exhausted'};
12+
13+
bool _isTransientFirestoreError(FirestoreError e) => e.code != null && _transientFirestoreCodes.contains(e.code);
14+
1015
class _RawQueryDoc {
1116
const _RawQueryDoc(this.id, this.data);
1217

@@ -539,48 +544,61 @@ class FirestoreTrackedClient implements FirestoreClient {
539544
required String sourceTag,
540545
required String collection,
541546
String? docId,
547+
int maxRetries = 2,
542548
}) async {
543549
final Stopwatch sw = Stopwatch()..start();
544-
try {
545-
final T result = await _firestore.runTransaction<T>((Transaction transaction) {
546-
final _FirestoreTransactionBridge bridge = _FirestoreTransactionBridge(_firestore, transaction);
547-
return action(bridge);
548-
});
549-
await _emitTelemetry(
550-
FirestoreTelemetryEvent(
551-
timestamp: DateTime.now(),
552-
sourceTag: sourceTag,
553-
operation: FirestoreOperation.transaction,
554-
collection: collection,
555-
filtersHash: docId == null ? collection : '$collection:$docId',
556-
durationMs: sw.elapsedMilliseconds,
557-
docId: docId,
558-
success: true,
559-
),
560-
);
561-
return result;
562-
} catch (error) {
563-
final FirestoreError mapped = mapFirestoreError(error);
564-
if (mapped.code == 'permission-denied') {
565-
logger.w(
566-
'[Firestore] permission-denied on transaction — collection: $collection, sourceTag: $sourceTag',
567-
error: mapped,
550+
int attempt = 0;
551+
while (true) {
552+
try {
553+
final T result = await _firestore.runTransaction<T>((Transaction transaction) {
554+
final _FirestoreTransactionBridge bridge = _FirestoreTransactionBridge(_firestore, transaction);
555+
return action(bridge);
556+
});
557+
await _emitTelemetry(
558+
FirestoreTelemetryEvent(
559+
timestamp: DateTime.now(),
560+
sourceTag: sourceTag,
561+
operation: FirestoreOperation.transaction,
562+
collection: collection,
563+
filtersHash: docId == null ? collection : '$collection:$docId',
564+
durationMs: sw.elapsedMilliseconds,
565+
docId: docId,
566+
success: true,
567+
),
568568
);
569+
return result;
570+
} catch (error) {
571+
final FirestoreError mapped = mapFirestoreError(error);
572+
if (_isTransientFirestoreError(mapped) && attempt < maxRetries) {
573+
attempt++;
574+
final int delayMs = (500 * math.pow(2, attempt - 1)).round();
575+
logger.w(
576+
'[Firestore] transient error (${mapped.code}) on transaction — retrying ($attempt/$maxRetries) after ${delayMs}ms, sourceTag: $sourceTag',
577+
);
578+
await Future<void>.delayed(Duration(milliseconds: delayMs));
579+
continue;
580+
}
581+
if (mapped.code == 'permission-denied') {
582+
logger.w(
583+
'[Firestore] permission-denied on transaction — collection: $collection, sourceTag: $sourceTag',
584+
error: mapped,
585+
);
586+
}
587+
await _emitTelemetry(
588+
FirestoreTelemetryEvent(
589+
timestamp: DateTime.now(),
590+
sourceTag: sourceTag,
591+
operation: FirestoreOperation.transaction,
592+
collection: collection,
593+
filtersHash: docId == null ? collection : '$collection:$docId',
594+
durationMs: sw.elapsedMilliseconds,
595+
docId: docId,
596+
success: false,
597+
errorCode: mapped.code,
598+
),
599+
);
600+
throw mapped;
569601
}
570-
await _emitTelemetry(
571-
FirestoreTelemetryEvent(
572-
timestamp: DateTime.now(),
573-
sourceTag: sourceTag,
574-
operation: FirestoreOperation.transaction,
575-
collection: collection,
576-
filtersHash: docId == null ? collection : '$collection:$docId',
577-
durationMs: sw.elapsedMilliseconds,
578-
docId: docId,
579-
success: false,
580-
errorCode: mapped.code,
581-
),
582-
);
583-
throw mapped;
584602
}
585603
}
586604

lib/core/widgets/menuButton/favWallpaperButton.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@ class _FavouriteWallpaperButtonState extends State<FavouriteWallpaperButton> {
8383
}
8484
context.favouriteWallsAdapter(listen: false).favCheck(wall).then((value) {
8585
analytics.track(FavStatusChangedEvent(wallId: wall.id, provider: wall.source.legacyProviderString));
86-
setState(() {
87-
isLoading = false;
88-
});
86+
if (mounted) {
87+
setState(() {
88+
isLoading = false;
89+
});
90+
}
8991
});
9092
}
9193
}

0 commit comments

Comments
 (0)