notificationGoToSettingsMaxAskCount property

int? get notificationGoToSettingsMaxAskCount

Maximum number of "go to settings" prompts shown to a permanently-denied user. Returns null when unlimited (cooldown is the sole gate).

Layered resolution:

  • Env override: --dart-define notificationGoToSettingsMaxAskCount=N. Default -1 means "unset, fall through" — this env-layer -1 is the "unset" marker and can never be returned (the guard if (envValue != -1) excludes it). Any other value — including 0 and negatives — is returned as-is. This matches the existing dreamic env "-1 = unset" convention used by notificationMaxAskCount; --dart-define notificationGoToSettingsMaxAskCount=0 returns 0.

  • Remote Config: positive int returns the clamped value. RC values 0 or negative mean "unset, fall through to programmatic default" (Firebase RC returns 0 for unset keys). This is layer-specific and does NOT contradict the inline helper API contract — at the inline helper layer, maxAskCount: 0 and negatives mean "never re-prompt"; at this RC layer, 0 and negatives mean "unset". The two layers have different signatures (RC returns non-nullable int; inline accepts int?).

  • Programmatic default (set via notificationGoToSettingsMaxAskCountDefault): stored in defaultRemoteConfig as a non-null int. "Unlimited" is stored as the notificationMaxAskCountUnlimited sentinel (-1) and mapped back to null here; every other stored value — including 0 — passes through unchanged (so a programmatic default = 0 resolves to 0, "never prompt").

    Two meanings of -1 coexist in this getter a few lines apart: the env-override layer's -1 means "unset, fall through" (above) and is never returned; the stored programmatic-default -1 is the "unlimited" sentinel mapped to null below. Same literal, different layer, different meaning — do not conflate them.

Default: null (unlimited), stored as the notificationMaxAskCountUnlimited sentinel.

Implementation

static int? get notificationGoToSettingsMaxAskCount {
  const envValue =
      int.fromEnvironment('notificationGoToSettingsMaxAskCount', defaultValue: -1);
  if (envValue != -1) {
    return envValue;
  }
  final remoteValue =
      g<RemoteConfigRepoInt>().getInt('notificationGoToSettingsMaxAskCount');
  if (remoteValue > 0) {
    final bounds = configBounds['notificationGoToSettingsMaxAskCount']!;
    return remoteValue.clamp(bounds.min, bounds.max);
  }
  // RC value <= 0 (including 0 and negatives) → unset, fall through to the
  // programmatic default. The default is stored as a non-null int; only the
  // sentinel maps to null (unlimited), every other value (incl. 0) is
  // returned as-is.
  final d = defaultRemoteConfig['notificationGoToSettingsMaxAskCount'] as int;
  return d == notificationMaxAskCountUnlimited ? null : d;
}