Fixes the notifier for feature flags and updates the example

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2025-05-13 14:31:21 +02:00
parent e6646d308c
commit 515c7fb5b1
2 changed files with 138 additions and 119 deletions
+126 -111
View File
@@ -147,42 +147,47 @@ class _ArcaneLoggingExampleState extends State<ArcaneLoggingExample> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return ValueListenableBuilder(
padding: const EdgeInsets.all(16.0), valueListenable: Arcane.features.notifier,
child: SizedBox( builder: (context, enabledFeatures, _) {
height: 200, return Padding(
child: Column( padding: const EdgeInsets.all(16.0),
crossAxisAlignment: CrossAxisAlignment.start, child: SizedBox(
children: [ height: 200,
Text( child: Column(
"Logging", crossAxisAlignment: CrossAxisAlignment.start,
style: Theme.of(context).textTheme.headlineSmall, children: [
Text(
"Logging",
style: Theme.of(context).textTheme.headlineSmall,
),
if (latestLogs.isEmpty)
Text(
"Log messages will appear here",
style: Theme.of(context).textTheme.labelSmall?.copyWith(
fontStyle: FontStyle.italic,
),
),
if (Feature.logging.disabled)
Text(
"Logging feature is disabled.",
style: Theme.of(context).textTheme.labelSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
Expanded(
child: ListView.builder(
itemCount: latestLogs.length,
itemBuilder: (context, index) {
return Text(latestLogs[index]);
},
),
),
],
), ),
if (latestLogs.isEmpty) ),
Text( );
"Log messages will appear here", },
style: Theme.of(context).textTheme.labelSmall?.copyWith(
fontStyle: FontStyle.italic,
),
),
if (Feature.logging.disabled)
Text(
"Logging feature is disabled.",
style: Theme.of(context).textTheme.labelSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
Expanded(
child: ListView.builder(
itemCount: latestLogs.length,
itemBuilder: (context, index) {
return Text(latestLogs[index]);
},
),
),
],
),
),
); );
} }
} }
@@ -200,47 +205,52 @@ class ArcaneAuthExample extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Card( return ValueListenableBuilder(
child: Padding( valueListenable: Arcane.features.notifier,
padding: const EdgeInsets.all(8.0), builder: (context, enabledFeatures, _) {
child: ValueListenableBuilder( return Card(
valueListenable: Arcane.auth.isSignedIn, child: Padding(
builder: (context, isSignedIn, _) { padding: const EdgeInsets.all(8.0),
return Column( child: ValueListenableBuilder(
mainAxisAlignment: MainAxisAlignment.spaceBetween, valueListenable: Arcane.auth.isSignedIn,
crossAxisAlignment: CrossAxisAlignment.stretch, builder: (context, isSignedIn, _) {
children: [ return Column(
Text( mainAxisAlignment: MainAxisAlignment.spaceBetween,
"Authentication", crossAxisAlignment: CrossAxisAlignment.stretch,
style: Theme.of(context).textTheme.headlineSmall, children: [
), Text(
ElevatedButton( "Authentication",
onPressed: Feature.authentication.enabled style: Theme.of(context).textTheme.headlineSmall,
? () async { ),
if (isSignedIn) { ElevatedButton(
await Arcane.auth.logOut(); onPressed: Feature.authentication.enabled
} else { ? () async {
await Arcane.auth.login<Credentials>( if (isSignedIn) {
input: ( await Arcane.auth.logOut();
email: "email", } else {
password: "password", await Arcane.auth.login<Credentials>(
), input: (
); email: "email",
} password: "password",
} ),
: null, );
child: Text( }
isSignedIn ? "Sign out" : "Sign in", }
), : null,
), child: Text(
Center( isSignedIn ? "Sign out" : "Sign in",
child: Text("Status: ${Arcane.auth.status.name}"), ),
), ),
], Center(
); child: Text("Status: ${Arcane.auth.status.name}"),
}, ),
), ],
), );
},
),
),
);
},
); );
} }
} }
@@ -414,42 +424,47 @@ class ArcaneFeatureFlagsExample extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Card( return ValueListenableBuilder(
child: Padding( valueListenable: Arcane.features.notifier,
padding: const EdgeInsets.all(8.0), builder: (context, enabledFeatures, _) {
child: Column( return Card(
mainAxisAlignment: MainAxisAlignment.spaceBetween, child: Padding(
crossAxisAlignment: CrossAxisAlignment.stretch, padding: const EdgeInsets.all(8.0),
children: [ child: Column(
Text( mainAxisAlignment: MainAxisAlignment.spaceBetween,
"Feature Flags", crossAxisAlignment: CrossAxisAlignment.stretch,
style: Theme.of(context).textTheme.headlineSmall, children: [
Text(
"Feature Flags",
style: Theme.of(context).textTheme.headlineSmall,
),
Expanded(
child: ListView.builder(
itemCount: Feature.values.length,
itemBuilder: (context, i) {
final Feature feature = Feature.values[i];
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(feature.name),
Switch(
value: feature.enabled,
onChanged: (_) {
feature.enabled
? feature.disable()
: feature.enable();
},
),
],
);
},
),
),
],
), ),
Expanded( ),
child: ListView.builder( );
itemCount: Feature.values.length, },
itemBuilder: (context, i) {
final Feature feature = Feature.values[i];
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(feature.name),
Switch(
value: feature.enabled,
onChanged: (_) {
feature.enabled
? feature.disable()
: feature.enable();
},
),
],
);
},
),
),
],
),
),
); );
} }
} }
@@ -70,8 +70,7 @@ class ArcaneFeatureFlags extends ArcaneService {
if (_enabledFeatures.contains(feature)) return I; if (_enabledFeatures.contains(feature)) return I;
_enabledFeatures.add(feature); _notifier.value = [..._enabledFeatures, feature];
_notifier.value.add(feature);
if (Arcane.logger.initialized) { if (Arcane.logger.initialized) {
Arcane.logger.log( Arcane.logger.log(
@@ -100,8 +99,7 @@ class ArcaneFeatureFlags extends ArcaneService {
if (!I._initialized) _init(); if (!I._initialized) _init();
if (!_enabledFeatures.contains(feature)) return I; if (!_enabledFeatures.contains(feature)) return I;
_enabledFeatures.remove(feature); _notifier.value = [..._enabledFeatures]..removeWhere((i) => i == feature);
_notifier.value.remove(feature);
if (Arcane.logger.initialized) { if (Arcane.logger.initialized) {
Arcane.logger.log( Arcane.logger.log(
@@ -123,8 +121,9 @@ class ArcaneFeatureFlags extends ArcaneService {
/// It is called automatically when enabling or disabling features if they haven't /// It is called automatically when enabling or disabling features if they haven't
/// already been initialized. /// already been initialized.
void _init() { void _init() {
_enabledFeatures.clear(); _notifier.value = [];
_notifier.value.clear();
notifier.addListener(_listener);
I._initialized = true; I._initialized = true;
notifyListeners(); notifyListeners();
@@ -135,10 +134,15 @@ class ArcaneFeatureFlags extends ArcaneService {
/// This method clears all enabled features, resets notification values, /// This method clears all enabled features, resets notification values,
/// marks the flags as uninitialized, and notifies listeners of the changes. /// marks the flags as uninitialized, and notifies listeners of the changes.
void reset() { void reset() {
_enabledFeatures.clear(); _notifier.value = [];
_notifier.value.clear();
I._initialized = false; I._initialized = false;
notifyListeners(); notifyListeners();
} }
void _listener() {
_enabledFeatures
..clear()
..addAll(notifier.value);
}
} }