fix(paywall): add dismiss controls and honest premium copy
The premium sheet had no close affordance or way to defer, and its copy only said "Función Premium" without stating what it unlocks. Adds a header close (X) button and a "not now" secondary action so dismissal is never harder than purchasing, and replaces the bare title with a concrete, honest breakdown of the 5 things premium unlocks (no ads, Android Auto, station recording, alarm vacation ranges, unlimited alarms) plus the one-time-purchase framing. The phone equalizer is never listed, since it stays free for everyone. New l10n keys added to all 13 locales.
This commit is contained in:
@@ -53,14 +53,42 @@ class HojaPremium extends StatelessWidget {
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
l10n.funcionPremium,
|
||||
l10n.premiumHojaTitulo,
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Explicit, obvious dismiss affordance (fix/import-alarmas-y-
|
||||
// paywall): a purchase sheet the user cannot easily escape is
|
||||
// a dark pattern and a Play policy risk. Reachable without
|
||||
// buying or restoring, same weight as any other icon button.
|
||||
IconButton(
|
||||
key: const ValueKey('hoja-premium-cerrar'),
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
tooltip: l10n.closeAction,
|
||||
onPressed: () => Navigator.of(context).maybePop(),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// Concrete, honest value list — accuracy is non-negotiable here:
|
||||
// these five are the ONLY things premium unlocks. The phone
|
||||
// equalizer stays free for everyone and must NEVER appear here;
|
||||
// only its Android Auto surface is affected, as a consequence of
|
||||
// Auto itself being gated.
|
||||
_BeneficioPremium(texto: l10n.premiumBeneficioSinAnuncios),
|
||||
_BeneficioPremium(texto: l10n.premiumBeneficioAndroidAuto),
|
||||
_BeneficioPremium(texto: l10n.premiumBeneficioGrabacion),
|
||||
_BeneficioPremium(texto: l10n.premiumBeneficioVacaciones),
|
||||
_BeneficioPremium(texto: l10n.premiumBeneficioAlarmasIlimitadas),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
l10n.premiumPagoUnico,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
// FIX 3 (code review): user-facing feedback for a failed
|
||||
// purchase/restore, or a restore that found nothing — before
|
||||
@@ -143,9 +171,49 @@ class HojaPremium extends StatelessWidget {
|
||||
: () => entitlement.restaurar(),
|
||||
child: Text(l10n.restaurarCompras),
|
||||
),
|
||||
if (!entitlement.esPremium) ...[
|
||||
const SizedBox(height: 4),
|
||||
// Clearly-labelled, always-reachable decline — same weight as
|
||||
// any other secondary action, never made harder to find than
|
||||
// buying (hard constraint: no dark patterns, no guilt-shaming
|
||||
// decline copy).
|
||||
TextButton(
|
||||
key: const ValueKey('hoja-premium-ahora-no'),
|
||||
onPressed: () => Navigator.of(context).maybePop(),
|
||||
child: Text(l10n.premiumAhoraNo),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// One concrete, honest value-list row (fix/import-alarmas-y-paywall).
|
||||
class _BeneficioPremium extends StatelessWidget {
|
||||
const _BeneficioPremium({required this.texto});
|
||||
|
||||
final String texto;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check_circle_rounded,
|
||||
size: 18,
|
||||
color: PluriWaveTokens.brand,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(texto, style: Theme.of(context).textTheme.bodyMedium),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user