Skip to content

Instantly share code, notes, and snippets.

@PlugFox
Last active February 15, 2024 13:11
Show Gist options
  • Save PlugFox/9e6b16890deacd0ae4855dae3491a149 to your computer and use it in GitHub Desktop.
Save PlugFox/9e6b16890deacd0ae4855dae3491a149 to your computer and use it in GitHub Desktop.
Firebase Remote Config - web implementation
/// Base interface
import 'remote_config_base.dart';
/// Conditional import
import 'remote_config_mobile.dart'
// ignore: uri_does_not_exist
if (dart.library.html) 'remote_config_web.dart';
...
final config = await getRemoteConfig();
...
...
<!-- SCRIPTS -->
<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-app.js"></script>
<!--<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-analytics.js"></script>-->
<!--<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-auth.js"></script>-->
<!--<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-firestore.js"></script>-->
<!--<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-database.js"></script>-->
<!--<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-storage.js"></script>-->
<!--<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-messaging.js"></script>-->
<!--<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-performance.js"></script>-->
<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-remote-config.js"></script>
<!--<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-functions.js"></script>-->
<script>
// Firebase configuration
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "..."
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
</script>
...
@JS()
library remote.config;
import 'dart:js_util' as js_util;
import 'package:js/js.dart';
import 'package:meta/meta.dart';
@JS('firebase.remoteConfig')
external _JSRemoteConfigInternal _getRemoteConfig();
@JS('Object.keys')
external List<String> _objectKeys(dynamic jsObject);
@JS()
@anonymous
class _JSRemoteConfigInternal {
external _JSRemoteConfigInternal();
@JS('defaultConfig')
external set defaultConfig(Object defaults);
@JS('defaultConfig')
external Object get defaultConfig;
@JS('fetchAndActivate')
external Future<void> fetchAndActivate();
@JS('getString')
external String getString(String key);
@JS('getNumber')
external num getNumber(String key);
@JS('getBoolean')
external bool getBoolean(String key);
}
/// The entry point for accessing Remote Config.
@immutable
class JsRemoteConfig with _JSConverter {
final _JSRemoteConfigInternal _internalDelegate;
static JsRemoteConfig _instance;
factory JsRemoteConfig() => _instance ??= JsRemoteConfig._internal();
JsRemoteConfig._internal() : _internalDelegate = _getRemoteConfig();
/// Sets the default config.
///
/// Default config parameters should be set then when changes are needed the
/// parameters should be updated in the Firebase console.
set defaultConfig(Map<String, Object> defaults) => _internalDelegate.defaultConfig = _mapToJsObject(defaults);
/// Gets the default config.
Map<String, Object> get defaultConfig => _jsObjectToMap(_internalDelegate.defaultConfig);
/// Activates the fetched config, makes fetched key-values take effect.
Future<void> fetchAndActivate() => js_util.promiseToFuture<void>(_internalDelegate.fetchAndActivate());
/// Gets the value corresponding to the [key] as a String.
///
/// If there is no parameter with corresponding [key] then the default
/// String value is returned.
String getString(String key) => _internalDelegate.getString(key);
/// Gets the value corresponding to the [key] as an number.
///
/// If there is no parameter with corresponding [key] then the default
/// number value is returned.
num getNumber(String key) => _internalDelegate.getNumber(key);
/// Gets the value corresponding to the [key] as an int.
///
/// If there is no parameter with corresponding [key] then the default
/// int value is returned.
int getInt(String key) => getNumber(key).toInt();
/// Gets the value corresponding to the [key] as a double.
///
/// If there is no parameter with corresponding [key] then the default double
/// value is returned.
double getDouble(String key) => getNumber(key).toDouble();
/// Gets the value corresponding to the [key] as a bool.
///
/// If there is no parameter with corresponding [key] then the default bool
/// value is returned.
bool getBoolean(String key) => _internalDelegate.getBoolean(key);
}
mixin _JSConverter {
Object _mapToJsObject(Map<String, Object> map) {
final Object jsObject = js_util.newObject();
for (final entry in map.entries) {
js_util.setProperty(jsObject, entry.key, entry.value);
}
return jsObject;
}
Map<String, Object> _jsObjectToMap(Object jsObject) {
final map = <String, Object>{};
if (jsObject == null || jsObject is String || jsObject is num || jsObject is bool) return map;
final keys = _objectKeys(jsObject);
for (final key in keys) {
map[key] = js_util.getProperty(jsObject, key);
}
return map;
}
}
final jsRemoteConfig = JsRemoteConfig();
jsRemoteConfig.defaultConfig = <String, Object>{
'stringValue': byDefault.stringValue,
'intValue': byDefault.intValue,
};
await jsRemoteConfig.fetchAndActivate().timeout(const Duration(seconds: 2));
final stringValue = jsRemoteConfig.getString('stringValue');
final intValue = jsRemoteConfig.getInt('intValue');
@Viacheslav-Romanov
Copy link

Awesome! Ready to create a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment