kubesense_flags_flutter 1.0.0
kubesense_flags_flutter: ^1.0.0 copied to clipboard
Flutter integration for the Kubesense Feature Flags and Experimentation SDK.
example/lib/main.dart
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0. This product includes software
// developed at Datadog (https://www.datadoghq.com/).
// Copyright 2019-Present Datadog, Inc.
// Modifications copyright 2026 KubeSense Technologies.
import 'dart:async';
import 'package:kubesense_flags_flutter/kubesense_flags_flutter.dart';
import 'package:kubesense_flutter_plugin/kubesense_flutter_plugin.dart';
import 'package:flutter/material.dart';
const _clientToken = String.fromEnvironment('KUBESENSE_CLIENT_TOKEN');
const _applicationId = String.fromEnvironment('KUBESENSE_APPLICATION_ID');
const _env = String.fromEnvironment('KUBESENSE_ENV', defaultValue: 'dev');
const _endpoint = String.fromEnvironment(
'KUBESENSE_RUM_ENDPOINT',
defaultValue: 'us2.kubesense.ai',
);
const _targetingKey = String.fromEnvironment(
'KUBESENSE_TARGETING_KEY',
defaultValue: 'example-user',
);
const _flagKey = String.fromEnvironment(
'KUBESENSE_FLAG_KEY',
defaultValue: 'checkout.enabled',
);
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final isConfigured = _clientToken.isNotEmpty;
if (isConfigured) {
final configuration = KubesenseConfiguration(
clientToken: _clientToken,
env: _env,
kubesenseRumEndpoint: _endpoint,
rumConfiguration: _applicationId.isEmpty
? null
: KubesenseRumConfiguration(applicationId: _applicationId),
)..addPlugin(const KubesenseFlagsPluginConfiguration());
await KubesenseSdk.instance.initialize(
configuration,
TrackingConsent.granted,
);
}
runApp(FlagsExampleApp(isConfigured: isConfigured));
}
class FlagsExampleApp extends StatefulWidget {
final bool isConfigured;
const FlagsExampleApp({
super.key,
required this.isConfigured,
});
@override
State<FlagsExampleApp> createState() => _FlagsExampleAppState();
}
class _FlagsExampleAppState extends State<FlagsExampleApp> {
String _status = 'idle';
FlagDetails<bool>? _details;
@override
void initState() {
super.initState();
unawaited(_evaluate());
}
Future<void> _evaluate() async {
if (!widget.isConfigured) {
setState(() {
_status =
'Set KUBESENSE_CLIENT_TOKEN with --dart-define to evaluate flags.';
});
return;
}
final client = KubesenseSdk.instance.flags?.sharedClient();
if (client == null) {
setState(() {
_status = 'Flags plugin is not configured.';
});
return;
}
setState(() {
_status = 'loading';
});
try {
await client.initialize(
const FlagsEvaluationContext(targetingKey: _targetingKey),
);
final details = client.getBooleanDetails(
key: _flagKey,
defaultValue: false,
);
setState(() {
_details = details;
_status = 'ready';
});
} catch (error) {
setState(() {
_details = null;
_status = 'using defaults: $error';
});
}
}
@override
Widget build(BuildContext context) {
final details = _details;
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Kubesense Flags')),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
_InfoRow(label: 'Status', value: _status),
_InfoRow(label: 'Environment', value: _env),
_InfoRow(label: 'Endpoint', value: _endpoint),
_InfoRow(label: 'Targeting key', value: _targetingKey),
const Divider(height: 32),
_InfoRow(label: 'Flag key', value: _flagKey),
_InfoRow(
label: 'Value',
value: details == null ? '(none)' : details.value.toString(),
),
_InfoRow(
label: 'Variant',
value: details?.variant ?? '(none)',
),
_InfoRow(
label: 'Error',
value: details?.error?.name ?? '(none)',
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _evaluate,
child: const Text('Evaluate flag'),
),
],
),
),
);
}
}
class _InfoRow extends StatelessWidget {
final String label;
final String value;
const _InfoRow({
required this.label,
required this.value,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 112,
child: Text(
label,
style: const TextStyle(fontWeight: FontWeight.w600),
),
),
Expanded(child: Text(value)),
],
),
);
}
}