Skip to main content

nudge 0.1.0 copy "nudge: ^0.1.0" to clipboard
nudge: ^0.1.0 copied to clipboard

A local-first nudge engine for Flutter. Log behavioural events on device, describe conditions with a fluent DSL and fire rate prompts, upsells and tips at the right moment, with cooldowns, caps, outco [...]

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:nudge/nudge.dart';

import 'nudges.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final nudge = await Nudge.initialize(
    ttl: const Duration(days: 90),
    maxCapacity: 1000,
  );
  registerNudges(nudge);

  runApp(const ExampleApp());
}

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) => MaterialApp(
    title: 'nudge example',
    theme: ThemeData(colorSchemeSeed: Colors.deepPurple),
    home: const ShopPage(),
  );
}

class ShopPage extends StatelessWidget {
  const ShopPage({super.key});

  Nudge get _nudge => Nudge.instance;

  Future<void> _completeOrder(BuildContext context) async {
    _nudge.logEvent(Events.orderCompleted, {'total': 42.5});

    // A natural pause: the order is done, the user is not in the middle of
    // a task. Ask the engine whether an interruptive prompt is due.
    final fire = _nudge.checkpoint(group: 'interruptive');
    if (fire == null || !context.mounted) return;

    final rated = await showDialog<bool>(
      context: context,
      builder: (context) => const RatingDialog(),
    );
    // With the real OS dialog the outcome is not observable: report
    // NudgeOutcome.unknown there.
    fire.complete(
      rated == true ? NudgeOutcome.accepted : NudgeOutcome.dismissed,
    );
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(title: const Text('nudge example')),
    body: ListView(
      padding: const EdgeInsets.all(16),
      children: [
        NudgeBuilder(
          condition: bigSpender(_nudge),
          builder: (context, isBigSpender) => isBigSpender
              ? const Card(
                  child: ListTile(
                    leading: Icon(Icons.star),
                    title: Text('Thanks for being a great customer!'),
                  ),
                )
              : const SizedBox.shrink(),
        ),
        FilledButton(
          key: const Key('complete_order'),
          onPressed: () => _completeOrder(context),
          child: const Text('Complete an order'),
        ),
        const SizedBox(height: 8),
        OutlinedButton(
          onPressed: () => _nudge.logEvent(Events.orderFailed),
          child: const Text('Fail an order'),
        ),
        const SizedBox(height: 24),
        const Text('Why is the rating prompt (not) eligible?'),
        const SizedBox(height: 8),
        const _Explanation(),
      ],
    ),
  );
}

/// Shows the live explanation of the rating prompt eligibility.
class _Explanation extends StatelessWidget {
  const _Explanation();

  @override
  Widget build(BuildContext context) {
    final nudge = Nudge.instance;
    final eligibility = nudge.nudges[Nudges.ratingPrompt]!.eligibility;

    return NudgeBuilder(
      // Rebuilds on eligibility changes; the explanation is recomputed then.
      condition: eligibility,
      builder: (context, _) => Text(
        nudge.explain(eligibility).toString(),
        style: const TextStyle(fontFamily: 'monospace'),
      ),
    );
  }
}

/// Stands in for the OS review dialog, which apps cannot customize.
class RatingDialog extends StatelessWidget {
  const RatingDialog({super.key});

  @override
  Widget build(BuildContext context) => AlertDialog(
    title: const Text('Enjoying the app?'),
    content: const Text('In a real app, call the in-app review API here.'),
    actions: [
      TextButton(
        onPressed: () => Navigator.pop(context, false),
        child: const Text('Not now'),
      ),
      FilledButton(
        onPressed: () => Navigator.pop(context, true),
        child: const Text('Rate'),
      ),
    ],
  );
}
0
likes
150
points
0
downloads

Documentation

API reference

Publisher

verified publisherangelocassano.it

Weekly Downloads

A local-first nudge engine for Flutter. Log behavioural events on device, describe conditions with a fluent DSL and fire rate prompts, upsells and tips at the right moment, with cooldowns, caps, outcomes and chaining.

Homepage
Repository (GitHub)
View/report issues

Topics

#engagement #analytics #nudge #triggers #rating

License

GPL-3.0 (license)

Dependencies

clock, flat_buffers, flutter, objectbox, objectbox_flutter_libs, path_provider, uuid

More

Packages that depend on nudge