From a003cae9d176acfa43c3e2bdecc9d8250822f272 Mon Sep 17 00:00:00 2001 From: Steven Hammond Date: Mon, 12 Jan 2026 16:26:04 -0500 Subject: [PATCH 1/4] Updates some versions in pubspec.lock The command dart pub get, made some updates to external package versions. --- example/pubspec.lock | 60 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index 3ddbfb9..7b926ba 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: path: ".." relative: true source: path - version: "0.4.0" + version: "0.4.1" async: dependency: transitive description: @@ -28,26 +28,26 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.19.1" crypto: dependency: transitive description: @@ -84,10 +84,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" ffi: dependency: transitive description: @@ -163,26 +163,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -195,10 +195,10 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: @@ -211,10 +211,10 @@ packages: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.17.0" package_info_plus: dependency: transitive description: @@ -235,10 +235,10 @@ packages: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_provider: dependency: transitive description: @@ -376,18 +376,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: @@ -408,10 +408,10 @@ packages: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.7" typed_data: dependency: transitive description: @@ -432,10 +432,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -477,5 +477,5 @@ packages: source: hosted version: "1.0.4" sdks: - dart: ">=3.5.0 <4.0.0" + dart: ">=3.8.0-0 <4.0.0" flutter: ">=3.24.0" From f7fc8f6d9d1823ce0f1928139936ecc3cb3599cc Mon Sep 17 00:00:00 2001 From: Steven Hammond Date: Mon, 12 Jan 2026 16:29:22 -0500 Subject: [PATCH 2/4] Namespaces all references to keys. Without a consistent namespacing of the keys (such as in init) there could be collisions with SharedPreferences settings from other packages or the app itself. This commit moves the namspacing into storage_manager_shared_prefs.dart and applies it to every key reference. --- lib/aptabase_flutter.dart | 2 +- lib/storage_manager_shared_prefs.dart | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/aptabase_flutter.dart b/lib/aptabase_flutter.dart index 795ae36..610a9c1 100644 --- a/lib/aptabase_flutter.dart +++ b/lib/aptabase_flutter.dart @@ -203,7 +203,7 @@ class Aptabase { "props": props, }); - final key = "aptabase_${time.millisecondsSinceEpoch}_$eventName"; + final key = "${time.millisecondsSinceEpoch}_$eventName"; await _storage.addEvent(key, body); } diff --git a/lib/storage_manager_shared_prefs.dart b/lib/storage_manager_shared_prefs.dart index 40ad1c7..d15d03f 100644 --- a/lib/storage_manager_shared_prefs.dart +++ b/lib/storage_manager_shared_prefs.dart @@ -2,6 +2,8 @@ import "package:aptabase_flutter/storage_manager.dart"; import "package:shared_preferences/shared_preferences.dart"; class StorageManagerSharedPrefs extends StorageManager { + static const _keyPrefix = "aptabase_"; + final _events = {}; @override @@ -9,8 +11,13 @@ class StorageManagerSharedPrefs extends StorageManager { final sharedPrefs = await SharedPreferences.getInstance(); final keys = sharedPrefs.getKeys(); for (final key in keys) { - final value = sharedPrefs.getString(key); - if (value != null) _events[key] = value; + if (key.startsWith(_keyPrefix)) { + final value = sharedPrefs.getString(key); + if (value != null) { + final unprefixedKey = key.substring(_keyPrefix.length); + _events[unprefixedKey] = value; + } + } } return super.init(); @@ -21,7 +28,7 @@ class StorageManagerSharedPrefs extends StorageManager { _events[key] = event; final sharedPrefs = await SharedPreferences.getInstance(); - await sharedPrefs.setString(key, event); + await sharedPrefs.setString("$_keyPrefix$key", event); } @override @@ -30,7 +37,7 @@ class StorageManagerSharedPrefs extends StorageManager { final sharedPrefs = await SharedPreferences.getInstance(); for (final key in keys) { - await sharedPrefs.remove(key); + await sharedPrefs.remove("$_keyPrefix$key"); } } From daa84175d4f0d43521e6fd2a1d97f9b34840ff5c Mon Sep 17 00:00:00 2001 From: Steven Hammond Date: Mon, 12 Jan 2026 16:44:09 -0500 Subject: [PATCH 3/4] Ensure consistent state between in memory and persisted events. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Update the _events map first, so that any errors accessing SharedPreferences do not prevent memory from being upated. 2. Add some error handling around SharedPreferences calls to avoid interrupting the flow if it isn’t necessary. --- lib/storage_manager_shared_prefs.dart | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/storage_manager_shared_prefs.dart b/lib/storage_manager_shared_prefs.dart index d15d03f..44181de 100644 --- a/lib/storage_manager_shared_prefs.dart +++ b/lib/storage_manager_shared_prefs.dart @@ -25,19 +25,34 @@ class StorageManagerSharedPrefs extends StorageManager { @override Future addEvent(String key, String event) async { - _events[key] = event; + try { + final sharedPrefs = await SharedPreferences.getInstance(); + final success = await sharedPrefs.setString("$_keyPrefix$key", event); - final sharedPrefs = await SharedPreferences.getInstance(); - await sharedPrefs.setString("$_keyPrefix$key", event); + if (success) { + _events[key] = event; + } + } catch (e) { + // If persistence fails, don't add to in-memory cache to maintain consistency + rethrow; + } } @override Future deleteEvents(Set keys) async { + // Remove from in-memory cache first since events were already sent _events.removeWhere((k, _) => keys.contains(k)); - final sharedPrefs = await SharedPreferences.getInstance(); - for (final key in keys) { - await sharedPrefs.remove("$_keyPrefix$key"); + try { + final sharedPrefs = await SharedPreferences.getInstance(); + for (final key in keys) { + await sharedPrefs.remove("$_keyPrefix$key"); + } + } catch (e) { + // Events were already sent successfully and removed from memory. + // Disk cleanup failure is not critical - orphaned keys will be cleaned + // up on next init if they still exist. + // Silently catch to avoid disrupting the event sending flow. } } From 7b62e8b59f1aaadedea0e6088206305ebd385790 Mon Sep 17 00:00:00 2001 From: Steven Hammond Date: Mon, 12 Jan 2026 16:49:48 -0500 Subject: [PATCH 4/4] Cache SharedPreferences Instance Get the shared preferences instance once during init. This prevents an async await call with every event. --- lib/storage_manager_shared_prefs.dart | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/storage_manager_shared_prefs.dart b/lib/storage_manager_shared_prefs.dart index 44181de..543badd 100644 --- a/lib/storage_manager_shared_prefs.dart +++ b/lib/storage_manager_shared_prefs.dart @@ -5,14 +5,15 @@ class StorageManagerSharedPrefs extends StorageManager { static const _keyPrefix = "aptabase_"; final _events = {}; + late final SharedPreferences _prefs; @override Future init() async { - final sharedPrefs = await SharedPreferences.getInstance(); - final keys = sharedPrefs.getKeys(); + _prefs = await SharedPreferences.getInstance(); + final keys = _prefs.getKeys(); for (final key in keys) { if (key.startsWith(_keyPrefix)) { - final value = sharedPrefs.getString(key); + final value = _prefs.getString(key); if (value != null) { final unprefixedKey = key.substring(_keyPrefix.length); _events[unprefixedKey] = value; @@ -26,8 +27,7 @@ class StorageManagerSharedPrefs extends StorageManager { @override Future addEvent(String key, String event) async { try { - final sharedPrefs = await SharedPreferences.getInstance(); - final success = await sharedPrefs.setString("$_keyPrefix$key", event); + final success = await _prefs.setString("$_keyPrefix$key", event); if (success) { _events[key] = event; @@ -44,9 +44,8 @@ class StorageManagerSharedPrefs extends StorageManager { _events.removeWhere((k, _) => keys.contains(k)); try { - final sharedPrefs = await SharedPreferences.getInstance(); for (final key in keys) { - await sharedPrefs.remove("$_keyPrefix$key"); + await _prefs.remove("$_keyPrefix$key"); } } catch (e) { // Events were already sent successfully and removed from memory.