telereso 0.0.9-alpha telereso: ^0.0.9-alpha copied to clipboard
Controle your application's resrouces (strings ,images) remotely using firebase and out of the box by extending your current implementation.
Telereso #
Flutter package to use Telereso,
Telereso will allow you to control your app resources (strings,images) remotely and out of the box , without the need to add extra logic ,
Installation #
Telereso depends on Firebase to use Remote Config for
resource management
And Cloud Messaging for realtime changes (optional)
All you need to get started is make sure your project has set up
firebase (check docs)
then just add Telereso
dependency to your project
dependencies:
telereso: ^0.0.9-alpha
Run pub get
.
Usage #
Initialization #
Initialization will not make api calls it's just to set up resources,
In your main.dart
file, call init()
:
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Telereso.instance.init();
return MaterialApp();
}
}
Full initialization options :
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Telereso.instance
.disableLog() // disable general and main logs
.enableDrawableLog() // allow drawable logs so you can debug your keys and fetched values
.enableStringsLog() // allow strings logs so you can debug your locals , keys and fetched values
.setRemoteConfigSettings(RemoteConfigSettings()) // if you have custom Remote Config settings pass them here
.setRemoteExpiration(const Duration(seconds: 1)) // provide your custom ducation , by defualt expiration will 12 hours, if reale time changes was enabled it will be 1 sec
.enableRealTimeChanges() // enable real time changes while developing
.init();
return MaterialApp();
}
}
Skipping the Initialization will not cause crashes, but the app will not be able to use the remote version of the resources, So it is a way to disable remote functionality.
Firebase #
Please follow the steps found here to set up your Remote Config correctly.
Localization #
According to Flutter Docs there is 2 ways to implement localization, Telereso support both
Minimal internationalization
If your app implement localization
using this approach,
All you need to do is do the following changes :
Extend BasicRemoteLocalizations
- Use
translateOrDefault()
to retrieve your string.
Example
Before:
class DemoLocalizations {
DemoLocalizations(this.localeName);
static Future<DemoLocalizations> load(Locale locale) {
final String name = locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final String localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((_) {
return DemoLocalizations(localeName);
});
}
static DemoLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, DemoLocalizations);
}
final String localeName;
String get title {
return Intl.message(
'Hello World',
name: 'title',
desc: 'Title for the Demo application',
locale: localeName,
);
}
}
After
class DemoLocalizations extends BasicRemoteLocalizations {
DemoLocalizations(this.locale) : super(locale: locale);
@override
final Locale locale;
static DemoLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, DemoLocalizations);
}
// Static member to have a simple access to the delegate from the MaterialApp
static const delegate = DemoLocalizationsDelegate();
static Map<String, Map<String, String>> _localizedValues = {
'en': {
'title': 'Hello World',
},
'es': {
'title': 'Hola Mundo',
},
};
String get title {
var key = 'title';
return translateOrDefault(key, _localizedValues[locale.languageCode][key]);
}
}
Internationalization based on the intl package
If your app implement localization
using this approach,
All you need to do is apply the following changes :
-
add telereso_generator to your
dev_dependencies
dev_dependencies: build_runner: ^1.0.0 telereso_generator: ^0.0.9-alpha
check telerso_generator usage
Run
pub get
. -
Add
build.yaml
in your project's root (next to l10n.yaml)targets: $default: builders: telereso_generator|telereso: enabled: true options: template-arb-file: app_en.arb output-localization-file: app_localizations.dart output-class: AppLocalizations output-class-remote: RemoteLocalizations
- Notice that first 3 options are the same as your l10n.yaml file, these flags has to be the same and required
output-class-remote
is the name of your new wrapper class, if not set it will beRemoteLocalizationsDefault
-
Build
flutter pub run build_runner build --delete-conflicting-outputs
Make sure a class named
remote_localizations.telereso.dart
was created next to yourarb
template -
Add RemoteLocalizations delegate above your
AppLocalizations.delegate
MaterialApp( localizationsDelegates: [ RemoteLocalizations.delegate //<---- add this AppLocalizations.delegate, //<---- keep this ], supportedLocales: [ const Locale('en') ], home: ... )
-
Start using your new wrapper
RemoteLocalizations
instead ofAppLocalizations
Example:
BEFORE
// In your Material/Widget/CupertinoApp: @override Widget build(BuildContext context) { return MaterialApp( onGenerateTitle: (BuildContext context) => AppLocalizations.of(context).appTitle, // ... ); }
After
// In your Material/Widget/CupertinoApp: @override Widget build(BuildContext context) { return MaterialApp( onGenerateTitle: (BuildContext context) => RemoteLocalizations.of(context).appTitle, // ... ); }
Asset Images #
You can make your asset images dynamic with one simple change,
Use RemoteImage.asset
instead of Image.asset
Example Before
....
child: Image.asset("assets/icons/image.png")
....
After
....
child: RemoteImage.asset("assets/icons/image.png"),
....
In Remote config console make sure to use full path assets/icons/image.png
as your key in your drawable
json, like:
{
"assets/icons/image.png": "<url>",
"assets/icons/image2.png": "<url2>"
}
Realtime changes #
For Remote Config setup follow steps found here
At your main app stateful widget (convert if needed) do the following changes :
- replace
StatefulWidget
withRemoteState
- add
firebaseMessaging
configurations
myBackgroundMessageHandler is not needed for Telereso
class HomePage extends StatefulWidget {
const HomePage({
Key key
}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends RemoteState<HomePage>{
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
static Future<dynamic> myBackgroundMessageHandler(
Map<String, dynamic> message) async {
// put your normal logic
if (message.containsKey('data')) {
// Handle data message
final dynamic data = message['data'];
}
if (message.containsKey('notification')) {
// Handle notification message
final dynamic notification = message['notification'];
}
// Or do other work.
}
@override
void initState() {
super.initState();
_firebaseMessaging.configure(
onMessage: (message) async {
if (await Telereso.instance.handleRemoteMessage(message)) return;
// put your normal logic
},
onBackgroundMessage: myBackgroundMessageHandler,
onLaunch: (message) async {},
onResume: (message) async {},
);
}
@override
Widget build(BuildContext context) {
return Stack(....);
}
}