{"id":15024590,"url":"https://github.com/telereso/telereso","last_synced_at":"2025-04-12T06:33:03.042Z","repository":{"id":40241716,"uuid":"333239062","full_name":"telereso/telereso","owner":"telereso","description":"Universal library to control your application resources remotely with easy, plug and play implementation","archived":false,"fork":false,"pushed_at":"2024-11-02T23:36:27.000Z","size":11776,"stargazers_count":8,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-03T22:51:09.974Z","etag":null,"topics":["android","firebase","flutter","hacktoberfest","ios","localization","react-native","remote","web"],"latest_commit_sha":null,"homepage":"https://www.telereso.io/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/telereso.png","metadata":{"files":{"readme":"README-template.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"patreon":"telereso"}},"created_at":"2021-01-26T22:52:19.000Z","updated_at":"2024-04-03T09:07:54.000Z","dependencies_parsed_at":"2025-02-12T22:01:30.362Z","dependency_job_id":"42ac9f07-0c40-4c15-861b-a71222487721","html_url":"https://github.com/telereso/telereso","commit_stats":{"total_commits":142,"total_committers":2,"mean_commits":71.0,"dds":"0.30281690140845074","last_synced_commit":"676af52ba64c9a9e66343d989de8f8c83d71b698"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/telereso%2Ftelereso","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/telereso%2Ftelereso/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/telereso%2Ftelereso/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/telereso%2Ftelereso/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/telereso","download_url":"https://codeload.github.com/telereso/telereso/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248530058,"owners_count":21119584,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","firebase","flutter","hacktoberfest","ios","localization","react-native","remote","web"],"created_at":"2024-09-24T20:00:37.099Z","updated_at":"2025-04-12T06:32:58.023Z","avatar_url":"https://github.com/telereso.png","language":"Kotlin","funding_links":["https://patreon.com/telereso"],"categories":[],"sub_categories":[],"readme":"![Banner](doc/banner.svg)\n\n[![jitpack](https://jitpack.io/v/telereso/telereso.svg)](https://jitpack.io/#telereso/telereso)\n[![Version](https://img.shields.io/cocoapods/v/Telereso.svg?style=flat)](https://cocoapods.org/pods/Telereso)\n[![Pub](https://img.shields.io/pub/v/telereso.svg)](https://pub.dartlang.org/packages/telereso)\n[![npm react native](https://img.shields.io/npm/v/telereso.svg)](https://www.npmjs.com/package/telereso)\n[![npm web](https://img.shields.io/npm/v/telereso-web.svg)](https://www.npmjs.com/package/telereso-web)\n\nTable of contents:\n\n* auto-gen TOC:\n{:toc}\n  \n## Installation\n\n[Telereso](https://telereso.io?utm_source=github\u0026utm_medium=readme\u0026utm_campaign=normal) depends on Firebase to\nuse [Remote Config](https://firebase.google.com/docs/remote-config/) for resource management\u003cbr\u003e\nAnd [Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) for realtime changes (_optional_)\n\nAll you need to get started is make sure your project has setup\nfirebase ([check docs](https://firebase.google.com/docs/guides)) \u003cbr\u003e\nthen just add [Telereso](https://telereso.io?utm_source=github\u0026utm_medium=readme\u0026utm_campaign=normal) dependency to your\nproject\n\n### Dependencies\n\n\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\u003cth\u003eApproach\u003c/th\u003e\u003cth\u003eInstruction\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"doc/gradle.png\" alt=\"Gradle\"/\u003e\u003c/td\u003e\n\u003ctd\u003e\n    \u003cpre\u003e\n// At your root build.gradle\nallprojects {\n    repositories {\n        // add JitPack repository\n        maven { url 'https://jitpack.io' }\n        jcenter()\n        google()\n    }\n}\u003c/pre\u003e\n    \u003cpre\u003e// At your app build.gradle\nimplementation \"io.telereso:telereso:${version}\"\u003c/pre\u003e\n    \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"doc/gradle.png\" alt=\"Gradle\"/\u003e (Kotlin DSL)\u003c/td\u003e\n\u003ctd\u003e\n    \u003cpre\u003e\n// At your root build.gradle\nallprojects {\n    repositories {\n        // add JitPack repository\n        maven { url 'https://jitpack.io' } \n        jcenter()\n        google()\n    }\n}\u003c/pre\u003e\n    \u003cpre\u003e// At your app build.gradle\nimplementation(\"io.telereso:telereso:${version}\")\u003c/pre\u003e\n    \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"doc/ios.png\" alt=\"IOS\"/\u003e\u003c/td\u003e\n\u003ctd\u003e\n    \u003cpre\u003e\npod 'Telereso'\n\u003c/pre\u003e\n    \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"doc/flutter.png\" alt=\"Flutter\"/\u003e\u003c/td\u003e\n\u003ctd\u003e\n    \u003cpre\u003e\ndependencies:\n  telereso: ^${flutterVersion}\n\u003c/pre\u003e\n    \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"doc/react-native.png\" alt=\"React Native\"/\u003e\u003c/td\u003e\n\u003ctd\u003e\n    \u003cpre\u003e\nnpm install telereso\n\u003c/pre\u003e\n    \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"doc/reactjs.png\" alt=\"React\"/\u003e\u003c/td\u003e\n\u003ctd\u003e\n    \u003cpre\u003e\nnpm install telereso-web\n\u003c/pre\u003e\n    \u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n## Samples \u0026 Examples\n\nNothing feels better than a snippet of code ready to be copied!\nCheck samples in this [repo](https://github.com/telereso/telereso/tree/master/Samples)\n\n* [Android](https://github.com/telereso/telereso/tree/master/Samples/android)\n* [IOS](https://github.com/telereso/telereso/tree/master/Samples/ios)\n* [Flutter](https://github.com/telereso/telereso/tree/master/Samples/flutter)\n* [React Native](https://github.com/telereso/telereso/tree/master/Samples/react-native)\n* [Web](https://github.com/telereso/telereso/tree/master/Samples/web)\n\n## Firebase\n\nThis section will show how to set up firebase remote config to be used\nwith [Telereso](https://telereso.io?utm_source=github\u0026utm_medium=readme\u0026utm_campaign=normal)\n\n### Strings\n\n#### Steps\n\n* Open [Firebase console](https://console.firebase.google.com/) then select Remote Config Dashboard\n* Add new param called `strings` \u003cbr\u003e\u003cbr\u003e\n  ![img.png](doc/add_strings.png)\u003cbr\u003e\u003cbr\u003e\n\n* Add a json containing key/value params representing your strings resource's key name (same key name found in the\n  strings.xml), and it's value \u003cbr\u003e\u003cbr\u003e![img.png](doc/param_value.png)\u003cbr\u003e\u003cbr\u003e\n* Add to `Strings` group  (this is optional but good practice) \u003cbr\u003e\u003cbr\u003e![img.png](doc/add_group.png) \u003cbr\u003e\u003cbr\u003e\n* Save and publish\n\n#### Localization\n\n[Telereso](https://telereso.io?utm_source=github\u0026utm_medium=readme\u0026utm_campaign=normal) supports localization using\nlocal after the strings prefix `strings_\u003clocal\u003e`\u003cbr\u003e\nTo support other languages just add more params each containing a json with same keys (as in the strings version) but\nwith a translated value \u003cbr\u003e\nex: `strings_fr,strings_ar...etc`\n\n_Android developers_ it will be the same local you add to your values dir `values-fr,values-ar...etc`\n\n_Notice we are using `_` instead of `-` due to remote config limitations_\n\n### Drawables\n\n#### Steps\n\n* Open [Firebase console](https://console.firebase.google.com/) then select Remote Config Dashboard\n* Add new param called `drawables`\n* Add a json containing key/value params representing your drawable resource's key name (same key name found in the\n  drawable dir), and it's value will be a url of your remote image \u003cbr\u003e\u003cbr\u003e![img.png](doc/add_drawable.png)\u003cbr\u003e\u003cbr\u003e\n* Add to `Drawables` group  (this is optional but good practice) \u003cbr\u003e\u003cbr\u003e![add_group](doc/add_group.png)\u003cbr\u003e\u003cbr\u003e\n* Save and publish\n\n#### Screens support\n\nTo support multiple screens sizes add parameters to different sizes `drawables_1x`, `drawables_2x`, `drawables_3x` \u003cbr\u003e\n`1x` being the lowest resolution and `3x` the highest \n\n### Final Result\n\n![final_result](doc/final_result.png)\n\n### Conditional Resources\n\nRemote Config provide conditions to be applied to your params (strings,drawables),\u003cbr\u003e\nThis will add another layer of dynamic delivery, so if you would like new versions to have specific resources,\u003cbr\u003e or\nsegment of users that clicked a button,\u003cbr\u003e\nOr strings and icons to be shown on specific days (Holidays 🎊🥳🎉!)...etc \u003cbr\u003e\u003cbr\u003e\nYou can see how [Telereso](https://telereso.io?utm_source=github\u0026utm_medium=readme\u0026utm_campaign=normal) will help avoid\nmultiple app releases.\n\u003cbr\u003e\u003cbr\u003e\n![img.png](doc/conditions_res.png)\n\n### A/B Testing\n\nOne of the great feature about Remote config is the out of the\nbox [A/B testing](https://firebase.google.com/docs/ab-testing) \u003cbr\u003e\nSince all our resources are indexed as params we could easily create experiments. \u003cbr\u003e\nThe following example show how we can test Drawer titles and see which one achieve higher conversion \u003cbr\u003e\u003cbr\u003e\n![img.png](doc/ab_testing.png)\n_This can be used for icons as well_\n\n## Usage\n\nThere are different scenarios to work\nwith [Telereso](https://telereso.io?utm_source=github\u0026utm_medium=readme\u0026utm_campaign=normal) ,\u003cbr\u003e\nWither you are starting a fresh new application, or an already in production application with large code base\n\n### Platforms\n* **Android**  \n  Follow docs [here in this page](https://telereso.io/#initialization) ,\u003cbr\u003e\n  You can use \u003ca href=\"https://plugins.jetbrains.com/plugin/16168-telereso\" target=\"_blank\"\u003eTelereso plugin\u003c/a\u003e to help you with the localization migration. \n\n* **IOS**  \n  Follow docs [here in this page](https://telereso.io/#initialization)\n\n* **Flutter**  \n  [Check package docs](https://pub.dev/packages/telereso#telereso)\n  \n* **React Native**  \n  [Check package docs](https://www.npmjs.com/package/telereso)\n\n* **Web**  \n  [Check package docs](https://www.npmjs.com/package/telereso-web)\n\n### Initialization\n\nInitialization By default will not make api calls it just to set up resources,\u003cbr\u003e\nIf your app has a splash screen it would be a perfect place to do this, or on your custom application class\u003cbr\u003e\nThe `init` function has a call back you can listen to,\u003cbr\u003e\nOr you could use the suspended version `suspendedInit` to make sure your app fetch the latest remote changes.\n\nSkipping the Initialization will not cause crashes, but the app will not be able to use the remote version of the\nresources,\u003cbr\u003e\nSo it is a way to disable remote functionality.\n\n**Application Start**\n\n\u003cdiv class=\"code-block kotlin java swift dart reactNative web\"\u003e\n\u003cdiv class=\"tab\"\u003e\n  \u003cbutton class=\"tablinks kotlin active\" onclick=\"openTab(event, 'kotlin')\"\u003eKotlin\u003c/button\u003e\n  \u003cbutton class=\"tablinks java\" onclick=\"openTab(event, 'java')\"\u003eJava\u003c/button\u003e\n  \u003cbutton class=\"tablinks swift\" onclick=\"openTab(event, 'swift')\"\u003eSwift\u003c/button\u003e\n  \u003cbutton class=\"tablinks dart\" onclick=\"openTab(event, 'dart')\"\u003eDart\u003c/button\u003e\n  \u003cbutton class=\"tablinks reactNative\" onclick=\"openTab(event, 'reactNative')\"\u003eReact Native\u003c/button\u003e\n  \u003cbutton class=\"tablinks web\" onclick=\"openTab(event, 'web')\"\u003eWeb\u003c/button\u003e\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent kotlin active\"\u003e\n\n{% highlight kotlin %}\n\n```kotlin\nclass MyApplication : Application() {\n   override fun onCreate() {\n      super.onCreate()\n      Telereso.init(this)\n   }\n}\n```\n\n{% endhighlight kotlin %}\n\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent java\"\u003e\n{% highlight java %}\n\n```java\npublic class MyApplication extends Application {\n   @Override\n   public void onCreate() {\n      super.onCreate();\n      Telereso.init(this);\n   }\n}\n```\n\n{% endhighlight java %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent swift\"\u003e\n{% highlight swift %}\n\n```swift\nclass AppDelegate: NSObject, UIApplicationDelegate {\n    \n    func application(_ application: UIApplication,\n        didFinishLaunchingWithOptions launchOptions:\n          [UIApplication.LaunchOptionsKey: Any]?) -\u003e Bool {\n        FirebaseApp.configure()\n        Telereso.initialize()\n        return true\n      }\n}\n```\n\n{% endhighlight swift %}\n\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent dart\"\u003e\n{% highlight dart %}\n\n```dart\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({\n    Key key,\n  }) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    Telereso.instance.init();\n    return MaterialApp();\n  }\n}\n```\n\n{% endhighlight dart %}\n\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent reactNative\"\u003e\n{% highlight kotlin %}\n\n```kotlin\nexport default class App extends React.Component {\n  render() {\n     return (\u003cAppContainer/\u003e);\n  }\n}\n\nTelereso.init(i18n);\n```\n{% endhighlight kotlin %}\n\n\u003c/div\u003e\n\u003cdiv class=\"tabcontent web\"\u003e\n{% highlight kotlin %}\n\n```kotlin\nimport App from \"./App\";\n\nimport i18n from \"./i18n\";\nimport {Telereso} from \"telereso-web\";\nimport firebase from \"firebase/app\";\n\n// Initialize Firebase\nconst firebaseConfig = {\n    apiKey: process.env.REACT_APP_FIREBASE_APIKEY,\n    authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,\n    projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,\n    storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,\n    messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,\n    appId: process.env.REACT_APP_FIREBASE_APP_ID,\n    measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID,\n};\nfirebase.initializeApp(firebaseConfig);\nTelereso.init(i18n,firebase);\n\nReactDOM.render(\n  \u003cReact.StrictMode\u003e\n\u003cApp/\u003e\n\u003c/React.StrictMode\u003e,\ndocument.getElementById('root')\n);\n```\n{% endhighlight kotlin %}\n\n\u003c/div\u003e\n\n\u003c/div\u003e\n\n**Splash Screen**\n\n\u003cdiv class=\"code-block kotlin java swift reactNative web\"\u003e\n\n\u003cdiv class=\"tab\"\u003e\n  \u003cbutton class=\"tablinks kotlin active\" onclick=\"openTab(event, 'kotlin')\"\u003eKotlin\u003c/button\u003e\n  \u003cbutton class=\"tablinks java\" onclick=\"openTab(event, 'java')\"\u003eJava\u003c/button\u003e\n  \u003cbutton class=\"tablinks swift\" onclick=\"openTab(event, 'swift')\"\u003eSwift\u003c/button\u003e\n  \u003cbutton class=\"tablinks reactNative\" onclick=\"openTab(event, 'reactNative')\"\u003eReact Native\u003c/button\u003e\n  \u003cbutton class=\"tablinks web\" onclick=\"openTab(event, 'web')\"\u003eWeb\u003c/button\u003e\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent kotlin active\"\u003e{% highlight kotlin %}\n\n```kotlin\nclass SplashActivity : Activity {\n   private override fun onCreate(savedInstanceState: Bundle?) {\n      super.onCreate(savedInstanceState);\n      Telereso.init(this) {\n        startActivity(Intent(this, MainActivity::class.java))\n        finish()\n      }\n   }\n}\n```\n\n{% endhighlight kotlin %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent java\"\u003e\n{% highlight java %}\n\n```java\npublic class SplashActivity extends Activity {\n   @Override\n   protected void onCreate(Bundle savedInstanceState) {\n      super.onCreate(savedInstanceState);\n      Telereso.init(this, () -\u003e {\n        startActivity(new Intent(this, MainActivity.class));\n        finish();\n        return null;\n      });\n   }\n}\n```\n\n{% endhighlight java %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent swift\"\u003e\n{% highlight swift %}\n\n```swift\nstruct ContentView: View {\n    @State private var result: Result\u003cBool, Error\u003e?\n    \n    func initTelereso(){\n        Telereso.initialize(){() -\u003e Void in\n            result = Result.success(true)\n        }\n    }\n    \n    var body: some View {\n        switch result {\n        case .success(_):\n            mainBody\n        case .failure(let error):\n            let _ = print(error)\n            mainBody\n        case nil:\n            ProgressView().onAppear(perform: initTelereso)\n        }\n    }\n}    \n```\n\n{% endhighlight swift %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent reactNative\"\u003e{% highlight kotlin %}\n\n```kotlin\nimport i18n from './i18n';\nimport { Telereso } from 'telereso';\n\nexport default class App extends React.Component {\n  state = {\n      splashFinished: false\n  }\n  constructor(props) {\n    super(props);\n    Telereso.suspendedInit(i18n).then(() =\u003e {\n      this.setState({\n          splashFinished: true\n      })\n    });\n  }\n\n  render() {\n    return (this.state.splashFinished ? \u003cAppContainer /\u003e : \u003cText\u003eLoading...\u003c/Text\u003e);\n  }\n}\n```\n\n{% endhighlight kotlin %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent web\"\u003e{% highlight kotlin %}\n\n```kotlin\nimport i18n from \"./i18n\";\nimport {Telereso} from \"telereso-web\";\nimport firebase from \"firebase/app\";\n\n\nexport default class App extends React.Component {\n\n  state = {\n      splashFinished: false\n  }\n\n  componentDidMount() {\n    Telereso.suspendedInit(i18n,firebase).then(() =\u003e {\n      this.setState({\n          splashFinished: true\n      })\n    });\n  }\n\n  render() {\n    return (this.state.splashFinished ? \u003cPricing/\u003e : \u003clabel\u003eLoading...\u003c/label\u003e);\n  }\n}\n```\n\n{% endhighlight kotlin %}\n\u003c/div\u003e\n\n\u003c/div\u003e\n\n**Full Options**\n\n\u003cdiv class=\"code-block kotlin java swift reactNative web\"\u003e\n\n\u003cdiv class=\"tab\"\u003e\n  \u003cbutton class=\"tablinks kotlin active\" onclick=\"openTab(event, 'kotlin')\"\u003eKotlin\u003c/button\u003e\n  \u003cbutton class=\"tablinks java\" onclick=\"openTab(event, 'java')\"\u003eJava\u003c/button\u003e\n  \u003cbutton class=\"tablinks swift\" onclick=\"openTab(event, 'swift')\"\u003eSwift\u003c/button\u003e\n  \u003cbutton class=\"tablinks reactNative\" onclick=\"openTab(event, 'reactNative')\"\u003eReact Native\u003c/button\u003e\n  \u003cbutton class=\"tablinks web\" onclick=\"openTab(event, 'web')\"\u003eWeb\u003c/button\u003e\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent kotlin active\"\u003e{% highlight kotlin %}\n\n```kotlin\nclass MyApplication : Application() {\n  override fun onCreate() {\n    super.onCreate()\n      Telereso.init(this)\n        .disableLog() // disable general and main logs \n        .enableStringLog() // enable strings logs to debug keys and fetched remote\n        .enableDrawableLog() // enable drawable logs to to debug keys and fetched remote\n        .enableRealTimeChanges() // enabled realtime changes , if realtime is disabled  remote is cached up to 12 horus\n  }\n}\n```\n\n{% endhighlight kotlin %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent java\"\u003e\n{% highlight java %}\n\n```java\npublic class MyApplication extends Application {\n  @Override\n  public void onCreate() {\n    super.onCreate();\n     Telereso.init(this)\n             .disableLog() // disable general and main logs \n             .enableStringLog() // enable strings logs to debug keys and fetched remote\n             .enableDrawableLog() // enable drawable logs to to debug keys and fetched remote\n             .enableRealTimeChanges(); // enabled realtime changes , if realtime is disabled  remote is cached up to 12 horus\n   }\n}\n```\n\n{% endhighlight java %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent swift\"\u003e\n{% highlight swift %}\n\n```swift\nclass AppDelegate: NSObject, UIApplicationDelegate {\n    \n    func application(_ application: UIApplication,\n        didFinishLaunchingWithOptions launchOptions:\n          [UIApplication.LaunchOptionsKey: Any]?) -\u003e Bool {\n        FirebaseApp.configure()\n        Telereso.enableRealTimeChanges().enableStringLog().initialize()\n        return true\n      }\n}\n```\n\n{% endhighlight swift %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent reactNative\"\u003e{% highlight kotlin %}\n\n```kotlin\nimport i18n from './i18n';\nimport { Telereso } from 'telereso';\n\nexport default class App extends React.Component {\n  state = {\n      splashFinished: false\n  }\n  constructor(props) {\n    super(props);\n    Telereso\n      .disableLog() // disable general logs\n      .enableStringsLog() // enable logs for string setup for debuging locals and remote setup\n      .enableDrawableLog() // enable drabel logs for debuging keys and urls fetched from remote\n      .setRemoteConfigSettings({minimumFetchIntervalMillis: 36000}) // if you have custome remote config settings provide them here\n      .enableRealTimeChanges() // to enable real time changes \n      .suspendedInit(i18n).then(() =\u003e {\n      this.setState({\n          splashFinished: true\n      })\n    });\n  }\n\n  render() {\n    return (this.state.splashFinished ? \u003cAppContainer /\u003e : \u003cText\u003eLoading...\u003c/Text\u003e);\n  }\n}\n```\n\n{% endhighlight kotlin %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent web\"\u003e{% highlight kotlin %}\n\n```kotlin\nimport i18n from \"./i18n\";\nimport {Telereso} from \"telereso-web\";\nimport firebase from \"firebase/app\";\n\n\nexport default class App extends React.Component {\n\n  state = {\n      splashFinished: false\n  }\n\n  componentDidMount() {\n    Telereso\n      .disableLog() // disable genral and main logs\n      .enableStringsLog() // enalbe initialization strings logs to debug current local and remote fetch\n      .enableDrawableLog() // enable drawable logs\n      .enableRealTimeChanges() // enable real time changes , by default remote cache is 12 hours , once enalbed will be 1 sec\n      .suspendedInit(i18n,firebase).then(() =\u003e {\n      this.setState({\n          splashFinished: true\n      })\n    });\n  }\n\n  render() {\n    return (this.state.splashFinished ? \u003cPricing/\u003e : \u003clabel\u003eLoading...\u003c/label\u003e);\n  }\n}\n```\n\n{% endhighlight kotlin %}\n\u003c/div\u003e\n\n\u003c/div\u003e\n\n#### Add `RemoteViewInflater` (Android)\n\nThis inflater will make sure all the android application views that display strings or images have the remote\nfunctionality,\u003cbr\u003e\nThe inflater will detect if you're setting the text in the xml directly like `andriod:text=@stirngs/user_name`\u003cbr\u003e\nAnd use the remote version if it's found or default back to the original value\u003cbr\u003e\n\nThe inflater handles the following views :\n\n* TextView\n* EditText\n* ImageView\n* Button\n* ImageButton\n* FloatingActionButton\n* BottomNavigationView\n* NavigationView\n\nyou can use the inflater with `App Theme` or `Activity Theme`\n\n*App Theme*\n\nIf your activities Does not use their own custom theme , add `RemoteViewInflater` directly to the app theme as\nthe `viewInflaterClass`\n\n```xml\n\n\u003cstyle name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\"\u003e\n    \u003citem name=\"colorPrimary\"\u003e@color/style_color_primary\u003c/item\u003e\n    \u003citem name=\"colorPrimaryDark\"\u003e@color/style_color_primary_dark\u003c/item\u003e\n    \u003citem name=\"colorAccent\"\u003e@color/style_color_accent\u003c/item\u003e\n    \u003citem name=\"colorControlHighlight\"\u003e@color/fab_color_pressed\u003c/item\u003e\n    \u003citem name=\"viewInflaterClass\"\u003eio.telereso.android.RemoteViewInflater\u003c/item\u003e\n\u003c/style\u003e\n```\n\n*Activity Theme*\n\nif your activity uses a custom theme add `RemoteViewInflater` to that theme\n\n```xml\n\n\u003cstyle name=\"AppTheme.TransparentActivity\"\u003e\n    \u003citem name=\"android:windowBackground\"\u003e@android:color/transparent\u003c/item\u003e\n    \u003citem name=\"android:windowIsTranslucent\"\u003etrue\u003c/item\u003e\n    \u003citem name=\"viewInflaterClass\"\u003eio.telereso.android.RemoteViewInflater\u003c/item\u003e\n\u003c/style\u003e\n```\n\n### Dynamic Resources\n\nSometimes we set the resrouces programmatically depending on a view state like so\n`title = getString(R.strings.title_home)`,\u003cbr\u003e\nIn this case we can use the Remote version of the function `getString()`\nwhich is\n`getRemoteString()`\u003cbr\u003e\nThis will make sure to use the remote version of the resource if found or default it to the original value\n\n**Strings**\n\u003cdiv class=\"code-block kotlin java swift dart reactNative web\"\u003e\n\u003cdiv class=\"tab\"\u003e\n  \u003cbutton class=\"tablinks kotlin active\" onclick=\"openTab(event, 'kotlin')\"\u003eKotlin\u003c/button\u003e\n  \u003cbutton class=\"tablinks java\" onclick=\"openTab(event, 'java')\"\u003eJava\u003c/button\u003e\n  \u003cbutton class=\"tablinks swift\" onclick=\"openTab(event, 'swift')\"\u003eSwift\u003c/button\u003e\n  \u003cbutton class=\"tablinks dart\" onclick=\"openTab(event, 'dart')\"\u003eDart\u003c/button\u003e\n  \u003cbutton class=\"tablinks reactNative\" onclick=\"openTab(event, 'reactNative')\"\u003eReact Native\u003c/button\u003e\n  \u003cbutton class=\"tablinks web\" onclick=\"openTab(event, 'web')\"\u003eWeb\u003c/button\u003e\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent kotlin active\"\u003e\n\n{% highlight kotlin %}\n\n```kotlin\ntitleTextView.text = getRemoteString(R.strings.title_home)\n```\n\n{% endhighlight kotlin %}\n\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent java\"\u003e\n{% highlight java %}\n\n```java\ntitleTextView.setText(Telereso.getRemoteString(R.strings.title_home));\n```\n\n{% endhighlight java %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent swift\"\u003e\n{% highlight swift %}\n\n```swift\n//UIKit\nlabel.text = Telereso.getRemoteString(\"title home\")\n\n//SwiftUI\nVStack{\n    Text(Telereso.getRemoteString(\"title home\"))\n}\n```\n\n{% endhighlight swift %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent dart\"\u003e\n{% highlight dart %}\n\n```dart\nWidget build(BuildContext context) {\n  return Text(\n    RemoteLocalizations.of(context).appTitle,\n  );\n}\n```\n\n{% endhighlight java %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent reactNative\"\u003e\n{% highlight kotlin %}\n\n```kotlin\nexport default class MyComponent extends React.Component {\n  render() {\n    return (\n      \u003cView\u003e\n          \u003cText\u003e{i18n.t('title_home')}\u003c/Text\u003e\n      \u003c/View\u003e\n    );\n  }\n}\n```\n\n{% endhighlight kotlin %}\n\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent web\"\u003e\n{% highlight kotlin %}\n\n```kotlin\nexport default class MyComponent extends React.Component {\n  render() {\n    return (\n      \u003cView\u003e\n          \u003cLabel\u003e{i18n.t('title_home')}\u003c/Lable\u003e\n      \u003c/View\u003e\n    );\n  }\n}\n```\n\n{% endhighlight kotlin %}\n\n\u003c/div\u003e\n\n\u003c/div\u003e\n\n**Drawables**\n\u003cdiv class=\"code-block kotlin java dart reactNative web\"\u003e\n\u003cdiv class=\"tab\"\u003e\n  \u003cbutton class=\"tablinks kotlin active\" onclick=\"openTab(event, 'kotlin')\"\u003eKotlin\u003c/button\u003e\n  \u003cbutton class=\"tablinks java\" onclick=\"openTab(event, 'java')\"\u003eJava\u003c/button\u003e\n  \u003cbutton class=\"tablinks dart\" onclick=\"openTab(event, 'dart')\"\u003eDart\u003c/button\u003e\n  \u003cbutton class=\"tablinks reactNative\" onclick=\"openTab(event, 'reactNative')\"\u003eReact Native\u003c/button\u003e\n  \u003cbutton class=\"tablinks web\" onclick=\"openTab(event, 'web')\"\u003eWeb\u003c/button\u003e\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent kotlin active\"\u003e\n\n{% highlight kotlin %}\n\n```kotlin\nimageView.setRemoteImageResource(R.id.icon)\n```\n\n{% endhighlight kotlin %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent java\"\u003e\n{% highlight java %}\n\n```java\nTelereso.setRemoteImageResource(imageView,R.id.icon);\n```\n\n{% endhighlight java %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent dart\"\u003e\n{% highlight dart %}\n\n```dart\nWidget build(BuildContext context) {\n  return RemoteImage.asset(\"assets/icons/image.png\");\n}\n```\n\n{% endhighlight dart %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent reactNative\"\u003e\n{% highlight kotlin %}\n\n```kotlin\nimport RemoteImage from 'telereso';\n\nexport default class MyComponent extends React.Component {\n  render() {\n    return (\n      \u003cView\u003e\n          \u003cRemoteImage source={require('../assets/icons/image.png')} /\u003e\n      \u003c/View\u003e\n    );\n  }\n}\n```\n\n{% endhighlight kotlin %}\n\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent web\"\u003e\n{% highlight kotlin %}\n\n```kotlin\nimport RemoteImage from 'telereso-web';\nimport logo from \"./assets/images/img.png\";\n\nexport default class MyComponent extends React.Component {\n  render() {\n    return (\n        \u003cRemoteImage src={logo} /\u003e\n    );\n  }\n}\n```\n\n{% endhighlight kotlin %}\n\n\u003c/div\u003e\n\n\u003c/div\u003e\n\n#### Dynamic Resources (out of the box, only android)\n\nIf you have a large code base and have a lot of `getString()` and `setImageResource`, \u003cbr\u003e\nAnd replacing them with a remote version is not an option,\u003cbr\u003e\nYou can override the activity's context with a `RemoteWrapperContext`\u003cbr\u003e\nThat will take care of the changes for you without any code changes.\n\n**Important note** if your app supports both portrait and land scape you need to handle the configuration changes\nmanually,\u003cbr\u003e\nLater versions of [Telereso](https://telereso.io?utm_source=github\u0026utm_medium=readme\u0026utm_campaign=normal) will address\nthis issue\n\nAdd the following to all your activities or your `BaseActivity`\n\n\u003cdiv class=\"code-block kotlin java\"\u003e\n\u003cdiv class=\"tab\"\u003e\n  \u003cbutton class=\"tablinks kotlin active\" onclick=\"openTab(event, 'kotlin')\"\u003eKotlin\u003c/button\u003e\n  \u003cbutton class=\"tablinks java\" onclick=\"openTab(event, 'java')\"\u003eJava\u003c/button\u003e\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent kotlin active\"\u003e\n\n{% highlight kotlin %}\n\n```kotlin\nclass MainActivity : Activity {\n   override fun attachBaseContext(newBase: Context) {\n      super.attachBaseContext(RemoteContextWrapper(newBase));\n   }\n}\n```\n\n{% endhighlight kotlin %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent java\"\u003e\n{% highlight java %}\n\n```java\npublic class MainActivity extends Activity {\n   @Override\n   protected void attachBaseContext(Context newBase) {\n      super.attachBaseContext(new RemoteContextWrapper(newBase));\n   }\n}\n```\n\n{% endhighlight java %}\n\u003c/div\u003e\n\u003c/div\u003e\n\n### Realtime Changes\n\nWho doesn't love to see changes happening in real time ?\u003cbr\u003e\n[Telereso](https://telereso.io?utm_source=github\u0026utm_medium=readme\u0026utm_campaign=normal) support this optional\nimplantation with some extra steps.\u003cbr\u003e\n\n_We recommend enabling this while in development mode only_\n\n**Cloud function**\n\nCreate a cloud function to be triggered when updating remote config, you can follow [this setup doc](https://firebase.google.com/docs/remote-config/propagate-updates-realtime) to do so,\u003cbr\u003e\n_PS: only follow the cloud function part_ \u003cbr\u003e\u003cbr\u003e\npackage.json\u003cbr\u003e\n\n ```json\n {\n   \"name\": \"sample-firebase-remoteconfig\",\n   \"version\": \"0.0.1\",\n   \"dependencies\": {\n     \"firebase-admin\": \"^9.4.2\",\n     \"firebase-functions\": \"^3.13.1\"\n   }\n }\n ```\n\u003cbr\u003e\nindex.js\n\n```javascript\nconst functions = require('firebase-functions');\nconst admin = require('firebase-admin');\nadmin.initializeApp();\n\n\nexports.pushConfig = functions.remoteConfig.onUpdate(versionMetadata =\u003e {\n// Create FCM payload to send data message to PUSH_RC topic.\nconst payload = {\n  topic: \"TELERESO_PUSH_RC\",\n  data: {\n    \"TELERESO_CONFIG_STATE\": \"STALE\"\n  }\n};\n// Use the Admin SDK to send the ping via FCM.\nreturn admin.messaging().send(payload).then(resp =\u003e {\n  console.log(resp);\n  return null;\n});\n});\n```\n\n_Notice the topic : **TELERESO_PUSH_RC** and data **TELERESO_CONFIG_STATE** has to the same_\n\n**Client**\n\nIn your android project add th following code in your `MyFirebaseMessagingService`:\u003cbr\u003e\u003cbr\u003e\n\u003cdiv class=\"code-block kotlin java dart reactNative\"\u003e\n\u003cdiv class=\"tab\"\u003e  \n\u003cbutton class=\"tablinks kotlin active\" onclick=\"openTab(event, 'kotlin')\"\u003eKotlin\u003c/button\u003e  \n\u003cbutton class=\"tablinks java\" onclick=\"openTab(event, 'java')\"\u003eJava\u003c/button\u003e  \n\u003cbutton class=\"tablinks dart\" onclick=\"openTab(event, 'dart')\"\u003eDart\u003c/button\u003e  \n\u003cbutton class=\"tablinks reactNative\" onclick=\"openTab(event, 'reactNative')\"\u003eReact Native\u003c/button\u003e  \n\u003c/div\u003e  \n\u003cdiv class=\"tabcontent kotlin active\"\u003e{% highlight kotlin %}\n\n```kotlin\nclass MyFirebaseMessagingService: FirebaseMessagingService() {\n  override fun onNewToken(token: String) {\n      if (BuildConfig.DEBUG)\n          Telereso.subscriptToChanges()\n  }   \n  override fun onMessageReceived(remoteMessage:RemoteMessage) {\n      if (BuildConfig.DEBUG \u0026\u0026 Telereso.handleRemoteMessage(getApplicationContext(), remoteMessage)) return\n      // your logic\n  }\n}\n```\n{% endhighlight kotlin %}\n\u003c/div\u003e\n\u003cdiv class=\"tabcontent java\"\u003e{% highlight java %}\n\n```java\npublic class MyFirebaseMessagingService extends FirebaseMessagingService {\n    @Override\n    public void onNewToken(String token) {\n        if (BuildConfig.DEBUG)\n            Telereso.subscriptToChanges();\n    }\n    @Override\n    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {\n        if (BuildConfig.DEBUG \u0026\u0026 Telereso.handleRemoteMessage(getApplicationContext(), remoteMessage))\n            return;\n        // your logic\n    }\n}\n```\n{% endhighlight java %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent dart\"\u003e{% highlight dart %}\n\n```dart\nclass _HomePageState extends RemoteState\u003c_HomePage\u003e {\n  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();\n\n  static Future\u003cdynamic\u003e myBackgroundMessageHandler(\n          Map\u003cString, dynamic\u003e message) async {\n    // put your normal logic\n  }\n  \n  @override\n  void initState() {\n    super.initState();\n    _firebaseMessaging.configure(\n      onMessage: (message) async {\n        if (await Telereso.instance.handleRemoteMessage(message)) return;\n        // put your normal logic\n      },\n      onBackgroundMessage: myBackgroundMessageHandler,\n      onLaunch: (message) async {},\n      onResume: (message) async {},\n    );\n    Telereso.instance.subscribeToChanges();\n  }\n}\n```\n{% endhighlight dart %}\n\u003c/div\u003e\n\n\u003cdiv class=\"tabcontent reactNative\"\u003e{% highlight kotlin %}\n\n```kotlin\nimport RemoteComponent from 'telereso';\n\nexport default class MyComponent extends RemoteComponent {\n  render() {\n    return (\n      \u003cView\u003e\n          \u003cText\u003e{i18n.t('title_home')}\u003c/Text\u003e\n      \u003c/View\u003e\n    );\n  }\n}\n```\n{% endhighlight kotlin %}\n\n\u003c/div\u003e\n\u003c/div\u003e\n\n## Telereso API\n\nHere are tables to help you use the library.\n\n### Kotlin\n\n|Function|Description|\n|--------|-----------|\n|`init(Context,finishCallback)`|setup resources to be used,finishCallback will be called as soon resources are ready, also will fetchAndActivate Remote config but will not block the init (finishCallback will be called before the fetch finishes)|\n|`suspendedInit(Context,finishCallback)`|used inside other suspended functions or coroutines, it will fetchAndActivate Remote config then setup resources)|\n|`Context.getRemoteString(R.string.\u003cstring_id\u003e)`|return remote string or original value|\n|`View.getRemoteString(R.string.\u003cstring_id\u003e)`|return remote string or original value|\n|`View.getRemoteString(R.string.\u003cstring_id\u003e)`|return remote string or original value|\n|`ImageView.setRemoteImageResource(R.string.\u003cres_id\u003e)`|set remote image resource or the original value|\n\n### Java\n\n|Function|Description|\n|--------|-----------|\n|`Telereso.init(Context,finishCallback)`|setup resources to be used,finishCallback will be called as soon resources are ready, also will fetchAndActivate Remote config but will not block the init (finishCallback will be called before the fetch finishes)|\n|`Telereso.getRemoteString(Context, R.string.\u003cstring_id\u003e)`|return remote string or original value|\n|`Teleresoset.getRemoteImageResource(ImageView,R.string.\u003cres_id\u003e)`|set remote image resource or the original value|\n\n## Getting Help\n\nTo report bugs, please use the GitHub project.\n\n* Project Page: [https://github.com/telereso/telereso](https://github.com/telereso/telereso)\n* Reporting Bugs: [https://github.com/telereso/telereso/issues](https://github.com/telereso/telereso/issues)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftelereso%2Ftelereso","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftelereso%2Ftelereso","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftelereso%2Ftelereso/lists"}