dvAnalyticsDirectoryFor function

String? dvAnalyticsDirectoryFor({
  1. required String appId,
  2. required String os,
  3. required Map<String, String> environment,
  4. String? androidStateDirectory,
  5. String leaf = 'dartvel-analytics',
  6. String variable = 'DARTVEL_ANALYTICS_DIR',
})

The directory appId's analytics database goes in on os, or null when the platform gives no directory that survives a restart.

DARTVEL_ANALYTICS_DIR wins everywhere. The rest is the per-user data directory each platform keeps across reboots, by the rules crash records follow: Android's files directory (it sets no HOME), Application Support on Apple platforms, LOCALAPPDATA on Windows, XDG elsewhere. Never the temporary directory, which the system clears -- a consent store that disappears asks the person again every launch -- and null rather than a relative guess, which on a device resolves against /.

androidStateDirectory is the device runtime's directory inside the application's files directory.

Implementation

String? dvAnalyticsDirectoryFor({
  required String appId,
  required String os,
  required Map<String, String> environment,
  String? androidStateDirectory,
  // Another device-local store kept beside this one -- the offline data
  // models' -- names its own folder and override here, and gets the same
  // per-platform rules.
  String leaf = 'dartvel-analytics',
  String variable = 'DARTVEL_ANALYTICS_DIR',
}) {
  String? usable(String? value) {
    if (value == null) return null;
    String trimmed = value.trim();
    while (trimmed.length > 1 &&
        (trimmed.endsWith('/') || trimmed.endsWith(r'\'))) {
      trimmed = trimmed.substring(0, trimmed.length - 1);
    }
    if (trimmed.isEmpty || trimmed == '/' || trimmed == r'\') return null;
    return trimmed;
  }

  final String? declared = usable(environment[variable]);
  if (declared != null) return declared;
  switch (os) {
    case 'android':
      final String? state = usable(androidStateDirectory);
      if (state == null) return null;
      final int slash = state.lastIndexOf('/');
      final String? files =
          slash <= 0 ? null : usable(state.substring(0, slash));
      return files == null ? null : '$files/$leaf';
    case 'ios':
    case 'macos':
      final String? home = usable(environment['HOME']);
      return home == null
          ? null
          : '$home/Library/Application Support/$appId/$leaf';
    case 'windows':
      final String? base =
          usable(environment['LOCALAPPDATA']) ?? usable(environment['APPDATA']);
      return base == null ? null : '$base\\$appId\\$leaf';
    default:
      final String? data = usable(environment['XDG_DATA_HOME']);
      if (data != null) return '$data/$appId/$leaf';
      final String? home = usable(environment['HOME']);
      return home == null ? null : '$home/.local/share/$appId/$leaf';
  }
}