Created
March 4, 2024 02:08
-
-
Save lukepighetti/344095c57c962cfa86af97f9115b8a4b to your computer and use it in GitHub Desktop.
My way of showing a paywall every day for a few days, then every week, then every two weeks. Good for about a year.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:collection/collection.dart'; | |
import 'package:shared_preferences/shared_preferences.dart'; | |
import '/architecture/let.dart'; | |
import '/membership/membership_state.dart'; | |
import '/membership/membership_tasks.dart'; | |
import '/telemetry/analytics.dart'; | |
Future<void> appOpenAction() async { | |
$analytics.vglAppOpenActionRequested(); | |
final prefs = await SharedPreferences.getInstance(); | |
final now = DateTime.now(); | |
final first = prefs.firstDate ??= now; | |
final last = prefs.lastDate ?? DateTime(2020); | |
final today = now.difference(first).inDays; | |
final lastDay = last.difference(first).inDays; | |
final nextDay = schedule.next(lastDay); | |
// We've completed the entire schedule! | |
if (nextDay == null || nextDay > today) { | |
$analytics.vglAppOpenActionSkip(); | |
} else { | |
$analytics.vglAppOpenActionShown(); | |
prefs.lastDate = now; | |
_handleAppOpenAction(); | |
} | |
} | |
void _handleAppOpenAction() { | |
if (!$revenueCat.proOrGrandfathered) { | |
showPaywall(PaywallReferrer.appOpen); | |
} | |
} | |
Iterable<int> get schedule sync* { | |
var x = -1; | |
for (var i = 1; i < 30; i++) { | |
switch (i) { | |
case <= 4: | |
x += 1; | |
case <= 7: | |
x += 4; | |
case <= 14: | |
x += 7; | |
case _: | |
x += 14; | |
} | |
yield x; | |
} | |
} | |
extension on SharedPreferences { | |
DateTime? get firstDate => getString('la-fd')?.let(DateTime.tryParse); | |
set firstDate(DateTime? x) => setString('la-fd', x?.toIso8601String() ?? ''); | |
DateTime? get lastDate => getString('la-ld')?.let(DateTime.tryParse); | |
set lastDate(DateTime? x) => setString('la-ld', x?.toIso8601String() ?? ''); | |
Future<void> clearDates() async { | |
await remove('la-fd'); | |
await remove('la-ld'); | |
} | |
} | |
Future<void> clearAppOpenActionDates() => | |
SharedPreferences.getInstance().then((x) => x.clearDates()); | |
extension on Iterable<int> { | |
Iterable<(int, int)> get pairwise sync* { | |
for (var i = 0; i < length - 1; i++) { | |
yield (elementAt(i), elementAt(i + 1)); | |
} | |
} | |
int? next(int needle) { | |
final s = sorted((a, z) => a - z); | |
for (final (i, (a, b)) in s.pairwise.indexed) { | |
if (i == 0 && needle < a) { | |
return a; | |
} | |
if (a <= needle && needle < b) { | |
return b; | |
} | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment