follow_up 0.1.0
follow_up: ^0.1.0 copied to clipboard
Forced, localized gospel-invitation flow for Flutter apps: shows after N app opens with a full-screen animated presentation.
example/lib/main.dart
import 'package:device_preview/device_preview.dart';
import 'package:flutter/material.dart';
import 'package:follow_up/follow_up.dart';
void main() {
runApp(DevicePreview(enabled: true, builder: (context) => const MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'follow_up example',
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)),
useInheritedMediaQuery: true,
builder: DevicePreview.appBuilder,
home: const DemoHome(),
);
}
}
/// Demo host screen. In a real app, [FollowUpGate] would wrap your actual
/// home widget with production defaults (openThreshold: 40, delay: 10s).
/// Here the threshold/delay are lowered and a debug panel is added so you
/// can see the flow without opening the app 40 times.
class DemoHome extends StatefulWidget {
const DemoHome({super.key});
@override
State<DemoHome> createState() => _DemoHomeState();
}
const _demoThreshold = 3;
class _DemoHomeState extends State<DemoHome> {
// Bumped to force FollowUpGate to remount (re-run its init/trigger logic)
// after a debug reset.
int _gateGeneration = 0;
Future<void> _forceTriggerNow() async {
final tracker = await FollowUpTracker.create();
await tracker.debugForceReady(threshold: _demoThreshold);
setState(() => _gateGeneration++);
}
@override
Widget build(BuildContext context) {
return FollowUpGate(
key: ValueKey(_gateGeneration),
openThreshold: _demoThreshold,
delay: const Duration(seconds: 3),
// Forces Arabic for this demo regardless of the device's real locale;
// omit `locale` in your own app to auto-detect from the device instead.
locale: const Locale('ar'),
// ctaUrl left at its default (FollowUpGate.defaultCtaUrl); pass your
// own to override, or null to disable the URL launch.
onInterested: (context) async {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Thanks for your interest! (onInterested callback fired)')),
);
},
child: Scaffold(
appBar: AppBar(title: const Text('follow_up example')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'This screen is wrapped in FollowUpGate.\n\n'
'Demo config: shows after 3 "opens" + 3s delay, instead of '
'the 40 opens / 10s production default.',
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
ElevatedButton(
onPressed: _forceTriggerNow,
child: const Text('Force-trigger the flow now'),
),
],
),
),
),
),
);
}
}