truesight_flutter
Core library for TrueSight team's Flutter applications.
- Introduction
- Getting Started
- Installation
- Usage
- Widget Documentation
- Custom Image Provider
- Cookie Management
- Date and Time Formats
- Additional Information
Getting Started
To install this package, run:
flutter pub add truesight_flutter go_router intl
Dependencies
This package depends on some libraries that must be installed manually:
dependencies:
# ...others
carbon_icons:
git: https://github.com/thanhtunguet/carbon-icons.git
Usage
JSON Serialization
The library provides the following classes:
DataModel
: Represents an entity in the application, typically mapped to a table in the backend database.DataFilter
: Filter set for a specificDataModel
.
Convention: Each DataModel
should have a corresponding DataFilter
.
Entities and filters in the application should extend these two classes.
To define a new class, consider the following example with the AppUser
class:
class AppUser extends DataModel {
@override
List<JsonField> get fields => [
username,
password,
email,
isAdmin,
dateOfBirth,
age,
level,
manager,
members,
];
JsonString username = JsonString('username', isRequired: false, helper: 'Username of the user');
JsonString password = JsonString('password', isRequired: false, helper: 'Password of the user');
JsonString email = JsonString('email', isRequired: false, helper: 'Email of the user');
JsonBoolean isAdmin = JsonBoolean('isAdmin', isRequired: false, helper: 'Is the user an admin');
JsonDate dateOfBirth = JsonDate('dateOfBirth', isRequired: false, helper: 'User\'s date of birth');
JsonInteger age = JsonInteger('age', isRequired: false, helper: 'Age of the user');
JsonDouble level = JsonDouble('level', isRequired: false, helper: 'Level of the user');
JsonObject<AppUser> manager = JsonObject('manager', isRequired: false, helper: 'Manager of the user');
JsonList<AppUser> members = JsonList<AppUser>('members', isRequired: false, helper: 'Members that this user manages');
}
Explanation:
fields
getter: These are the JSON fields that will be automatically mapped from JSON when fetching data from the backend.- JSON data fields are represented by the following classes:
Class | Dart Data Type |
---|---|
JsonDate |
DateTime |
JsonBoolean |
bool |
JsonString |
String |
JsonInteger |
int |
JsonDouble |
double |
JsonNumber |
num |
JsonObject |
DataModel |
JsonList |
List<DataModel> |
The JsonXYZ
classes inherit from JsonField
.
Mapping Data from JSON
final json = await requestFromAPI();
AppUser user = AppUser();
user.fromJSON(json);
Converting to JSON
AppUser user = AppUser();
user.toJSON(); // Returns the JSON representation of the user, typically a Dart Map object.
user.toString(); // Returns the JSON representation of the user as a Dart String.
Advanced Filters
Similar to JSON classes, the library defines FilterField
data types as follows:
Class | Dart Data Type | JSON Data Type |
---|---|---|
StringFilter |
String |
JsonString |
DateFilter |
DateTime |
JsonDate |
GuidFilter |
String |
JsonString |
IdFilter |
int |
JsonInteger |
IntFilter |
int |
JsonInteger |
DoubleFilter |
double |
JsonDouble |
NumberFilter |
num |
JsonNumber |
HTTP Requests
The repository class performs API calls to the backend to fetch data.
Each HttpRepository
class can represent a set of APIs corresponding to a specific business logic, such as user login (UserRepository
) or product management (ProductRepository
).
The HttpRepository
class can be used with the @singleton
annotation from the injectable
package combined with get_it
for dependency injection.
Each method in HttpRepository
corresponds to a specific API.
@singleton
class UserRepository extends HttpRepository {
@override
InterceptorsWrapper interceptorWrapper = InterceptorsWrapper();
@override
String? get baseUrl => 'https://app.example.com';
Future<AppUser> login(String username, String password) {
return post("/login", data: {
'username': username,
'password': password,
})
.then((response) => response.body<AppUser>(AppUser));
}
}
TrueSightService
The TrueSightService
is a singleton class designed to handle application-wide settings and configuration management using Hive for local storage and dotenv for environment variable management. This service provides a way to initialize necessary configurations and manage settings like faceIdEnabled
and baseApiUrl
.
Initialization
initialize
Initializes the service with optional parameters to enable dotenv and Hive.
Parameters
enableDotenv
(bool): Iftrue
, loads environment variables using theflutter_dotenv
package. Default istrue
.enableHive
(bool): Iftrue
, initializes Hive and opens a box for storage. Default istrue
.
Usage
await truesightService.initialize(
enableDotenv: true,
enableHive: true,
);
Properties
faceIdEnabled
Getter and setter for the faceIdEnabled
setting. This setting controls whether Face ID is enabled in the application.
Getter
Returns a bool
indicating whether Face ID is enabled. If the value is not set, it defaults to true
.
Setter
Sets the faceIdEnabled
value.
Usage
// Get faceIdEnabled
bool isFaceIdEnabled = truesightService.faceIdEnabled;
// Set faceIdEnabled
truesightService.faceIdEnabled = false;
baseApiUrl
Getter and setter for the baseApiUrl
setting. This setting holds the base URL for the API. If the value is not set, it falls back to the environment variable BASE_API_URL
.
Getter
Returns a String
containing the base API URL. If the value is not set in Hive, it retrieves the value from the environment variables.
Setter
Sets the baseApiUrl
value.
Usage
// Get baseApiUrl
String apiUrl = truesightService.baseApiUrl;
// Set baseApiUrl
truesightService.baseApiUrl = 'https://api.example.com';
Private Methods
_getOrCreate
A utility method to retrieve a value from Hive or create it with a default value if it does not exist.
Parameters
key
(String): The key for the value in Hive.defaultValue
(dynamic): The default value to use if the key does not exist.
Returns
- The value associated with the key, or the default value if the key does not exist.
Example
Here's an example of how to use the TrueSightService
in a Flutter application:
import 'package:flutter/material.dart';
import 'path_to_your_service/truesight_app_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await truesightService.initialize();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Truesight App Service Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Face ID Enabled: ${truesightService.faceIdEnabled}'),
Text('Base API URL: ${truesightService.baseApiUrl}'),
ElevatedButton(
onPressed: () {
truesightService.faceIdEnabled = !truesightService.faceIdEnabled;
},
child: Text('Toggle Face ID'),
),
ElevatedButton(
onPressed: () {
truesightService.baseApiUrl = 'https://newapi.example.com';
},
child: Text('Set New API URL'),
),
],
),
),
),
);
}
}
Custom Image Provider
A custom image provider designed to fetch images with appended authentication tokens from the server.
Overview
The TrueSightImageProvider
class extends ImageProvider<Uri>
and modifies image loading behavior to include authentication tokens fetched from cookies.
Constructor
TrueSightImageProvider(String url)
Constructs an instance of TrueSightImageProvider
with the provided image URL.
Methods
-
obtainKey(ImageConfiguration configuration): Asynchronously obtains a key for the image. Appends authentication token to the URL's query parameters.
-
loadImage(Uri key, ImageDecoderCallback decode): Loads the image from the specified URL with authentication headers using an HTTP client. Tracks loading progress with chunk events.
Example Usage
import 'package:flutter/material.dart';
class MyImageWidget extends StatelessWidget {
final String imageUrl = 'https://example.com/image.jpg';
@override
Widget build(BuildContext context) {
final imageProvider = TrueSightImageProvider(imageUrl);
return Image(
image: imageProvider,
fit: BoxFit.cover,
);
}
}
In this example, TrueSightImageProvider
is used as the image provider for an Image
widget, ensuring the image is fetched with proper authentication.
Widget Documentation
- AppNavigationBar
- AppTitle
- BodyText
- CarbonButton
- ConfirmationDialog
- EllipsisText
- GoBackButton
- IconPlaceholder
- ImagePlaceholder
- SignInButton
- SimpleInfiniteList
- StatefulTextFormField
Cookie Management
In our app, cookies are managed to handle user sessions and authentication tokens efficiently. The cookies are stored using the SharedPreferences
package, which allows for persistent storage of key-value pairs on the device.
Overview
Cookies are essential for maintaining user sessions and handling authentication. The following extension methods and functions facilitate the storage, retrieval, and clearing of cookies in the app.
Storing Cookies
Cookies are parsed from the Set-Cookie
header and stored with a prefix in the SharedPreferences
. The parseSetCookie
function handles this parsing:
Map<String, String> parseSetCookie(String setCookieString) {
Map<String, String> cookies = {};
List<String> parts = setCookieString.split('; ');
if (parts.isNotEmpty && parts[0].contains('=')) {
List<String> keyValue = parts[0].split('=');
if (keyValue.length == 2) {
cookies[_getCookieKey(keyValue[0])] = keyValue[1];
}
}
return cookies;
}
Retrieving Cookies
Cookies are retrieved from the SharedPreferences
using the getCookies
function. This function retrieves all keys with the specified prefix and constructs a map of cookies:
Future<Map<String, dynamic>> getCookies() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final Set<String> keys = prefs.getKeys();
final Map<String, dynamic> prefsMap = {};
for (String key in keys) {
if (_isCookieKey(key)) {
prefsMap[_getCookieKeyReversed(key)] = prefs.get(key);
}
}
return prefsMap;
}
Clearing Cookies
Cookies can be cleared from the SharedPreferences
using the clearCookies
function. This function removes all keys with the specified prefix:
Future<void> clearCookies() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final Set<String> keys = prefs.getKeys();
for (String key in keys) {
if (_isCookieKey(key)) {
prefs.remove(key);
}
}
}
Cookie Extension Methods
The extension methods on Map<String, dynamic>
provide easy access to specific cookies, such as token
and refreshToken
:
extension TrueSightCookies on Map<String, dynamic> {
String? get token => this['Token'];
String? get refreshToken => this['RefreshToken'];
bool get hasToken => this['Token'] != null;
bool get hasRefreshToken => this['RefreshToken'] != null;
}
These methods simplify the retrieval and usage of cookies in various parts of the app.
Example Usage
Here is an example of how to use the cookie management functions in your app:
// Parsing and storing a Set-Cookie header
String setCookieHeader = 'Token=abc123; Path=/; HttpOnly';
Map<String, String> cookies = parseSetCookie(setCookieHeader);
// Store the parsed cookies using SharedPreferences
// ...
// Retrieving stored cookies
Future<void> printStoredCookies() async {
Map<String, dynamic> cookies = await getCookies();
print('Stored Token: ${cookies.token}');
}
// Clearing stored cookies
Future<void> clearStoredCookies() async {
await clearCookies();
print('Cookies cleared');
}
With these functions and extensions, managing cookies in your app becomes straightforward and efficient.
Date and Time Formats
Our app uses various date and time formats to ensure consistency and readability, especially tailored for the Vietnamese locale. The formats are defined in the DateTimeFormatsVN
class and can be easily used throughout the app.
Available Formats
The DateTimeFormatsVN
class defines several common date and time formats:
- Full Date and Time:
dd/MM/yyyy HH:mm:ss
- Example:
01/01/2024 14:30:45
- Example:
- Date and Time without Seconds:
dd/MM/yyyy HH:mm
- Example:
01/01/2024 14:30
- Example:
- Date Only:
dd/MM/yyyy
- Example:
01/01/2024
- Example:
- Time Only:
HH:mm:ss
- Example:
14:30:45
- Example:
- Day and Month Only:
dd/MM
- Example:
01/01
- Example:
- Year Only:
yyyy
- Example:
2024
- Example:
- Date with Day Name:
EEEE, dd/MM/yyyy
- Example:
Thứ Hai, 01/01/2024
- Example:
- Date with Month Name:
dd MMMM yyyy
- Example:
01 Tháng Giêng 2024
- Example:
- Short Date with Month Name:
dd MMM
- Example:
01 Thg 01
- Example:
Formatting Dates
The DateTimeFormatsVN
class includes a helper function to format DateTime
objects using the specified formats:
static String format(DateTime dateTime, String format) {
return DateFormat(format, 'vi').format(dateTime);
}
You can use this function to format dates according to the predefined formats. For example:
DateTime now = DateTime.now();
String formattedDate = DateTimeFormatsVN.format(now, DateTimeFormatsVN.dateTime);
print(formattedDate); // Output: 01/01/2024 14:30:45
Extension Method for DateTime
We have also provided an extension method on the DateTime
class to simplify the formatting process. This method uses a default format but allows for customization:
extension DateTimeFormatter on DateTime {
String format({
String dateFormat = DateTimeFormatsVN.dateOnly,
}) {
return DateFormat(dateFormat).format(toLocal());
}
}
Example usage of the extension method:
DateTime now = DateTime.now();
String formattedDate = now.format();
print(formattedDate); // Output: 01/01/2024
String customFormattedDate = now.format(dateFormat: DateTimeFormatsVN.dateWithDayName);
print(customFormattedDate); // Output: Thứ Hai, 01/01/2024
Summary
By using the DateTimeFormatsVN
class and the DateTimeFormatter
extension, you can easily format dates and times in your app, ensuring consistency and localization for Vietnamese users.
Additional Information
This package is under development. Feel free to create an issue.
Libraries
- blocs/blocs
- blocs/user/user_bloc
- constants/constants
- extensions/extensions
- filters/filters
- json/json
- models/models
- providers/dio_image_provider
- providers/providers
- repositories/repositories
- services/error_handler_service
- services/file_service
- services/push_notification_service
- services/secure_storage_service
- services/services
- services/truesight_app_service
- styles/styles
- truesight_flutter
- widgets/app_title
- widgets/body_text
- widgets/confirmation_dialog
- widgets/ellipsis_text
- widgets/enum_status_badge
- widgets/icon_placeholder
- widgets/image_placeholder
- widgets/loading_indicator
- widgets/simple_infinite_list
- widgets/stateful_text_form_field
- widgets/text_status_badge
- widgets/widgets