Documentation Index
Fetch the complete documentation index at: https://docs.presentum.dev/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Storage tracks presentation events across sessions. This guide shows you how to implement thePresentumStorage interface.
Implementation
Use this generic go-to SharedPreferences storage implementation for any presentum:import 'dart:async';
import 'package:presentum/presentum.dart';
import 'package:shared_preferences/shared_preferences.dart';
typedef PersistentPresentumStorageKey<
S extends PresentumSurface,
V extends PresentumVisualVariant
> = (String itemId, S surface, V variant);
extension type PersistentPresentumStorageKeys<
S extends PresentumSurface,
V extends PresentumVisualVariant
>(PersistentPresentumStorageKey<S, V> key) {
String get shownCount =>
'__shown_${key.$1}_${key.$2.name}_${key.$3.name}_count_key__';
String get lastShown =>
'__shown_${key.$1}_${key.$2.name}_${key.$3.name}_last_shown_key__';
String get timestamps =>
'__shown_${key.$1}_${key.$2.name}_${key.$3.name}_timestamps_key__';
String get dismissedAt =>
'__dismissed_${key.$1}_${key.$2.name}_${key.$3.name}_at_key__';
String get convertedAt =>
'__converted_${key.$1}_${key.$2.name}_${key.$3.name}_at_key__';
List<String> get allKeys => [
shownCount,
lastShown,
timestamps,
dismissedAt,
convertedAt,
];
}
class PersistentPresentumStorage<
S extends PresentumSurface,
V extends PresentumVisualVariant
>
implements PresentumStorage<S, V> {
PersistentPresentumStorage({required SharedPreferencesWithCache prefs})
: _prefs = prefs;
final SharedPreferencesWithCache _prefs;
@override
Future<void> clearItem(
String itemId, {
required S surface,
required V variant,
}) => Future.wait(
PersistentPresentumStorageKeys((
itemId,
surface,
variant,
)).allKeys.map(_prefs.remove),
);
@override
FutureOr<DateTime?> getLastShown(
String itemId, {
required S surface,
required V variant,
}) async {
final key = PersistentPresentumStorageKeys((
itemId,
surface,
variant,
)).lastShown;
final timestampStr = _prefs.getString(key);
return timestampStr != null ? DateTime.parse(timestampStr) : null;
}
@override
FutureOr<void> recordShown(
String itemId, {
required S surface,
required V variant,
required DateTime at,
}) async {
final keys = PersistentPresentumStorageKeys((itemId, surface, variant));
final countKey = keys.shownCount;
final lastShownKey = keys.lastShown;
final timestampsKey = keys.timestamps;
final currentCount = _prefs.getInt(countKey) ?? 0;
final currentTimestamps = _prefs.getStringList(timestampsKey) ?? [];
await _prefs.setInt(countKey, currentCount + 1);
await _prefs.setString(lastShownKey, at.toIso8601String());
await _prefs.setStringList(timestampsKey, [
...currentTimestamps,
at.toIso8601String(),
]);
}
@override
FutureOr<int> getShownCount(
String itemId, {
required Duration period,
required S surface,
required V variant,
}) async {
final keys = PersistentPresentumStorageKeys((itemId, surface, variant));
final timestampsKey = keys.timestamps;
final timestampStrings = _prefs.getStringList(timestampsKey) ?? [];
final timestamps = timestampStrings.map(DateTime.parse).toList();
final cutoff = DateTime.now().subtract(period);
final count = timestamps.where((t) => t.isAfter(cutoff)).length;
return count;
}
@override
FutureOr<DateTime?> getDismissedAt(
String itemId, {
required S surface,
required V variant,
}) async {
final keys = PersistentPresentumStorageKeys((itemId, surface, variant));
final timestampStr = _prefs.getString(keys.dismissedAt);
return timestampStr != null ? DateTime.parse(timestampStr) : null;
}
@override
FutureOr<void> recordDismissed(
String itemId, {
required S surface,
required V variant,
required DateTime at,
}) async {
final keys = PersistentPresentumStorageKeys((itemId, surface, variant));
await _prefs.setString(keys.dismissedAt, at.toIso8601String());
}
@override
FutureOr<void> recordConverted(
String itemId, {
required S surface,
required V variant,
required DateTime at,
}) async {
final keys = PersistentPresentumStorageKeys((itemId, surface, variant));
await _prefs.setString(keys.convertedAt, at.toIso8601String());
}
}
See generic production storage
Complete SharedPreferences implementation