Skip to content

Commit 776ff7f

Browse files
committed
feat: Add centralized ErrorService for consistent error handling
1 parent 5a68c06 commit 776ff7f

15 files changed

+893
-35
lines changed

lib/controllers/authentication_controller.dart

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'dart:developer';
33
import 'package:appwrite/appwrite.dart';
44
import 'package:flutter/rendering.dart';
55
import 'package:resonate/services/appwrite_service.dart';
6+
import 'package:resonate/services/error_service.dart';
67
import 'package:flutter/material.dart';
78
import 'package:get/get.dart';
89
import 'package:resonate/controllers/auth_state_controller.dart';
@@ -36,7 +37,7 @@ class AuthenticationController extends GetxController {
3637
emailController.clear();
3738
passwordController.clear();
3839
} on AppwriteException catch (e) {
39-
log(e.toString());
40+
// Handle specific Appwrite auth errors with custom messages
4041
if (e.type == userInvalidCredentials) {
4142
customSnackbar(
4243
AppLocalizations.of(context)!.tryAgain,
@@ -53,14 +54,16 @@ class AuthenticationController extends GetxController {
5354
AppLocalizations.of(context)!.passwordShort,
5455
LogType.error,
5556
);
56-
5757
SemanticsService.announce(
5858
AppLocalizations.of(context)!.passwordShort,
5959
TextDirection.ltr,
6060
);
61+
} else {
62+
// Use ErrorService for other Appwrite errors
63+
ErrorService.handle(e, context: 'login');
6164
}
6265
} catch (e) {
63-
log(e.toString());
66+
ErrorService.handle(e, context: 'login');
6467
} finally {
6568
isLoading.value = false;
6669
}
@@ -75,14 +78,7 @@ class AuthenticationController extends GetxController {
7578
);
7679
return true;
7780
} catch (e) {
78-
log(e.toString());
79-
customSnackbar(
80-
AppLocalizations.of(context)!.oops,
81-
e.toString(),
82-
LogType.error,
83-
);
84-
SemanticsService.announce(e.toString(), TextDirection.ltr);
85-
81+
ErrorService.handle(e, context: 'signup');
8682
return false;
8783
} finally {
8884
isLoading.value = false;
@@ -93,15 +89,15 @@ class AuthenticationController extends GetxController {
9389
try {
9490
await authStateController.loginWithGoogle();
9591
} catch (error) {
96-
log(error.toString());
92+
ErrorService.handle(error, context: 'Google login');
9793
}
9894
}
9995

10096
Future<void> loginWithGithub() async {
10197
try {
10298
await authStateController.loginWithGithub();
10399
} catch (error) {
104-
log(error.toString());
100+
ErrorService.handle(error, context: 'GitHub login');
105101
}
106102
}
107103

lib/controllers/create_room_controller.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import 'dart:developer';
2+
23
import 'package:flutter/material.dart';
34
import 'package:get/get.dart';
45
import 'package:resonate/controllers/auth_state_controller.dart';
56
import 'package:resonate/controllers/tabview_controller.dart';
7+
import 'package:resonate/services/error_service.dart';
68
import 'package:resonate/themes/theme_controller.dart';
79
import 'package:resonate/utils/enums/room_state.dart';
810
import 'package:textfield_tags/textfield_tags.dart';
@@ -88,10 +90,9 @@ class CreateRoomController extends GetxController {
8890
tagsController.clearTags();
8991
descriptionController.clear();
9092
} catch (e) {
91-
log(e.toString());
92-
9393
// Close the loading dialog
9494
Get.back();
95+
ErrorService.handle(e, context: 'creating room');
9596
} finally {
9697
isLoading.value = false;
9798
}

lib/controllers/rooms_controller.dart

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ import 'package:loading_animation_widget/loading_animation_widget.dart';
99
import 'package:resonate/controllers/tabview_controller.dart';
1010
import 'package:resonate/models/appwrite_room.dart';
1111
import 'package:resonate/services/appwrite_service.dart';
12+
import 'package:resonate/services/error_service.dart';
1213
import 'package:resonate/services/room_service.dart';
1314
import 'package:resonate/themes/theme_controller.dart';
14-
import 'package:resonate/utils/enums/log_type.dart';
1515
import 'package:resonate/utils/enums/room_state.dart';
16-
import 'package:resonate/views/widgets/snackbar.dart';
1716

1817
import '../utils/constants.dart';
1918
import 'auth_state_controller.dart';
@@ -88,7 +87,7 @@ class RoomsController extends GetxController {
8887
}
8988
update();
9089
} catch (e) {
91-
log(e.toString());
90+
ErrorService.handleSilently(e, context: 'fetching rooms');
9291
} finally {
9392
isLoading.value = false;
9493
}
@@ -106,7 +105,8 @@ class RoomsController extends GetxController {
106105
AppwriteRoom appwriteRoom = await createRoomObject(room, userUid);
107106
return appwriteRoom;
108107
} catch (e) {
109-
log(e.toString());
108+
ErrorService.handleSilently(e, context: 'fetching room by ID');
109+
return null;
110110
}
111111
}
112112

@@ -140,11 +140,11 @@ class RoomsController extends GetxController {
140140
// Open the Room Bottom Sheet to interact in the room
141141
Get.find<TabViewController>().openRoomSheet(room);
142142
} catch (e) {
143-
log(e.toString());
144-
getRooms();
145-
update();
146143
// Close the loading dialog
147144
Get.back();
145+
ErrorService.handle(e, context: 'joining room');
146+
getRooms();
147+
update();
148148
}
149149
}
150150

@@ -163,12 +163,11 @@ class RoomsController extends GetxController {
163163
room.description.toLowerCase().contains(lowerQuery);
164164
}).toList();
165165
} catch (e) {
166-
log('Error searching rooms: $e');
167166
filteredRooms.value = rooms;
168-
customSnackbar(
169-
AppLocalizations.of(Get.context!)!.error,
170-
AppLocalizations.of(Get.context!)!.searchFailed,
171-
LogType.error,
167+
ErrorService.handle(
168+
e,
169+
context: 'searching rooms',
170+
userMessage: AppLocalizations.of(Get.context!)?.searchFailed,
172171
);
173172
} finally {
174173
isSearching.value = false;

lib/l10n/app_en.arb

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1808,7 +1808,66 @@
18081808
"usernameAlreadyTaken": "This username is already taken. Try a different one.",
18091809
"@usernameAlreadyTaken": {
18101810
"description": "Error shown when the chosen username is unavailable because another user has already registered it."
1811-
}
1811+
},
1812+
1813+
"networkError": "Please check your internet connection and try again.",
1814+
"@networkError": {
1815+
"description": "Error message shown when a network-related error occurs."
1816+
},
18121817

1818+
"authenticationError": "Authentication failed. Please try again.",
1819+
"@authenticationError": {
1820+
"description": "Generic error message for authentication failures."
1821+
},
1822+
1823+
"storageError": "Failed to save or load data. Please try again.",
1824+
"@storageError": {
1825+
"description": "Error message shown when file storage operations fail."
1826+
},
1827+
1828+
"databaseError": "Failed to access data. Please try again.",
1829+
"@databaseError": {
1830+
"description": "Error message shown when database operations fail."
1831+
},
1832+
1833+
"validationError": "Please check your input and try again.",
1834+
"@validationError": {
1835+
"description": "Error message shown when input validation fails."
1836+
},
1837+
1838+
"generalError": "Something went wrong. Please try again.",
1839+
"@generalError": {
1840+
"description": "Generic fallback error message for unexpected errors."
1841+
},
1842+
1843+
"connectionError": "Connection Error",
1844+
"@connectionError": {
1845+
"description": "Title for network connection error messages."
1846+
},
1847+
1848+
"authError": "Authentication Error",
1849+
"@authError": {
1850+
"description": "Title for authentication error messages."
1851+
},
1852+
1853+
"invalidInput": "Invalid Input",
1854+
"@invalidInput": {
1855+
"description": "Title for validation error messages."
1856+
},
1857+
1858+
"userAlreadyExists": "An account with this email already exists.",
1859+
"@userAlreadyExists": {
1860+
"description": "Error message when trying to create an account with an existing email."
1861+
},
1862+
1863+
"userNotFound": "User not found.",
1864+
"@userNotFound": {
1865+
"description": "Error message when a user account cannot be found."
1866+
},
1867+
1868+
"dataNotFound": "The requested data was not found.",
1869+
"@dataNotFound": {
1870+
"description": "Error message when requested data does not exist."
1871+
}
18131872

18141873
}

lib/l10n/app_localizations.dart

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,10 +1410,10 @@ abstract class AppLocalizations {
14101410
/// **'Please check your mail for a new OTP.'**
14111411
String get otpResentMessage;
14121412

1413-
/// Generic error message for network connection issues.
1413+
/// Title for network connection error messages.
14141414
///
14151415
/// In en, this message translates to:
1416-
/// **'There is a connection error. Please check your internet and try again.'**
1416+
/// **'Connection Error'**
14171417
String get connectionError;
14181418

14191419
/// The word 'seconds', often used after a countdown number.
@@ -1467,7 +1467,7 @@ abstract class AppLocalizations {
14671467
/// Error message when a chosen username is too short.
14681468
///
14691469
/// In en, this message translates to:
1470-
/// **'Username should contain more than 5 characters.'**
1470+
/// **'Username should contain more than 7 characters.'**
14711471
String get usernameCharacterLimit;
14721472

14731473
/// Generic button text for submitting a form.
@@ -2518,17 +2518,95 @@ abstract class AppLocalizations {
25182518
/// **'Are you sure you want to delete this message?'**
25192519
String get deleteMessageContent;
25202520

2521-
/// No description provided for @thisMessageWasDeleted.
2521+
/// Status text shown when a previously sent message has been deleted.
25222522
///
25232523
/// In en, this message translates to:
25242524
/// **'This message was deleted'**
25252525
String get thisMessageWasDeleted;
25262526

2527-
/// No description provided for @failedToDeleteMessage.
2527+
/// Error message shown when the system is unable to delete a message.
25282528
///
25292529
/// In en, this message translates to:
25302530
/// **'Failed to delete message'**
25312531
String get failedToDeleteMessage;
2532+
2533+
/// Validation error displayed when the user enters a username with unsupported characters.
2534+
///
2535+
/// In en, this message translates to:
2536+
/// **'Please enter a valid username. Only letters, numbers, dots, underscores, and hyphens are allowed.'**
2537+
String get usernameInvalidFormat;
2538+
2539+
/// Error shown when the chosen username is unavailable because another user has already registered it.
2540+
///
2541+
/// In en, this message translates to:
2542+
/// **'This username is already taken. Try a different one.'**
2543+
String get usernameAlreadyTaken;
2544+
2545+
/// Error message shown when a network-related error occurs.
2546+
///
2547+
/// In en, this message translates to:
2548+
/// **'Please check your internet connection and try again.'**
2549+
String get networkError;
2550+
2551+
/// Generic error message for authentication failures.
2552+
///
2553+
/// In en, this message translates to:
2554+
/// **'Authentication failed. Please try again.'**
2555+
String get authenticationError;
2556+
2557+
/// Error message shown when file storage operations fail.
2558+
///
2559+
/// In en, this message translates to:
2560+
/// **'Failed to save or load data. Please try again.'**
2561+
String get storageError;
2562+
2563+
/// Error message shown when database operations fail.
2564+
///
2565+
/// In en, this message translates to:
2566+
/// **'Failed to access data. Please try again.'**
2567+
String get databaseError;
2568+
2569+
/// Error message shown when input validation fails.
2570+
///
2571+
/// In en, this message translates to:
2572+
/// **'Please check your input and try again.'**
2573+
String get validationError;
2574+
2575+
/// Generic fallback error message for unexpected errors.
2576+
///
2577+
/// In en, this message translates to:
2578+
/// **'Something went wrong. Please try again.'**
2579+
String get generalError;
2580+
2581+
/// Title for authentication error messages.
2582+
///
2583+
/// In en, this message translates to:
2584+
/// **'Authentication Error'**
2585+
String get authError;
2586+
2587+
/// Title for validation error messages.
2588+
///
2589+
/// In en, this message translates to:
2590+
/// **'Invalid Input'**
2591+
String get invalidInput;
2592+
2593+
/// Error message when trying to create an account with an existing email.
2594+
///
2595+
/// In en, this message translates to:
2596+
/// **'An account with this email already exists.'**
2597+
String get userAlreadyExists;
2598+
2599+
/// Error message when a user account cannot be found.
2600+
///
2601+
/// In en, this message translates to:
2602+
/// **'User not found.'**
2603+
String get userNotFound;
2604+
2605+
/// Error message when requested data does not exist.
2606+
///
2607+
/// In en, this message translates to:
2608+
/// **'The requested data was not found.'**
2609+
String get dataNotFound;
25322610
}
25332611

25342612
class _AppLocalizationsDelegate

lib/l10n/app_localizations_bn.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,4 +1384,46 @@ class AppLocalizationsBn extends AppLocalizations {
13841384

13851385
@override
13861386
String get failedToDeleteMessage => 'বার্তা মুছে ফেলা ব্যর্থ হয়েছে';
1387+
1388+
@override
1389+
String get usernameInvalidFormat =>
1390+
'Please enter a valid username. Only letters, numbers, dots, underscores, and hyphens are allowed.';
1391+
1392+
@override
1393+
String get usernameAlreadyTaken =>
1394+
'This username is already taken. Try a different one.';
1395+
1396+
@override
1397+
String get networkError =>
1398+
'Please check your internet connection and try again.';
1399+
1400+
@override
1401+
String get authenticationError => 'Authentication failed. Please try again.';
1402+
1403+
@override
1404+
String get storageError => 'Failed to save or load data. Please try again.';
1405+
1406+
@override
1407+
String get databaseError => 'Failed to access data. Please try again.';
1408+
1409+
@override
1410+
String get validationError => 'Please check your input and try again.';
1411+
1412+
@override
1413+
String get generalError => 'Something went wrong. Please try again.';
1414+
1415+
@override
1416+
String get authError => 'Authentication Error';
1417+
1418+
@override
1419+
String get invalidInput => 'Invalid Input';
1420+
1421+
@override
1422+
String get userAlreadyExists => 'An account with this email already exists.';
1423+
1424+
@override
1425+
String get userNotFound => 'User not found.';
1426+
1427+
@override
1428+
String get dataNotFound => 'The requested data was not found.';
13871429
}

0 commit comments

Comments
 (0)