Nova tela de login | Adaptaçao nova da AppBar | Animções novas
This commit is contained in:
@@ -3,6 +3,9 @@ import 'dart:math' as math;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
import '../widgets/entrance.dart';
|
||||
import '../widgets/tap_bounce.dart';
|
||||
|
||||
class CuriosidadeScreen extends StatelessWidget {
|
||||
const CuriosidadeScreen({super.key});
|
||||
|
||||
@@ -68,24 +71,48 @@ class CuriosidadeScreen extends StatelessWidget {
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
|
||||
children: [
|
||||
_CuriosityTopicTile(
|
||||
title: 'Tema X',
|
||||
description: 'Aprenda dicas rápidas e simples para cuidar dos dentes no dia a dia.',
|
||||
FadeSlideIn(
|
||||
child: TapBounce(
|
||||
scale: 0.97,
|
||||
child: _CuriosityTopicTile(
|
||||
title: 'Tema X',
|
||||
description:
|
||||
'Aprenda dicas rápidas e simples para cuidar dos dentes no dia a dia.',
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const _CuriosityTopicTile(
|
||||
title: 'Tema Y',
|
||||
description: 'Conteúdo em breve.',
|
||||
FadeSlideIn(
|
||||
delay: const Duration(milliseconds: 60),
|
||||
child: const TapBounce(
|
||||
scale: 0.97,
|
||||
child: _CuriosityTopicTile(
|
||||
title: 'Tema Y',
|
||||
description: 'Conteúdo em breve.',
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const _CuriosityTopicTile(
|
||||
title: 'Tema Z',
|
||||
description: 'Conteúdo em breve.',
|
||||
FadeSlideIn(
|
||||
delay: const Duration(milliseconds: 120),
|
||||
child: const TapBounce(
|
||||
scale: 0.97,
|
||||
child: _CuriosityTopicTile(
|
||||
title: 'Tema Z',
|
||||
description: 'Conteúdo em breve.',
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const _CuriosityTopicTile(
|
||||
title: 'Tema U',
|
||||
description: 'Conteúdo em breve.',
|
||||
FadeSlideIn(
|
||||
delay: const Duration(milliseconds: 180),
|
||||
child: const TapBounce(
|
||||
scale: 0.97,
|
||||
child: _CuriosityTopicTile(
|
||||
title: 'Tema U',
|
||||
description: 'Conteúdo em breve.',
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -156,17 +183,21 @@ class _CuriosityTopicTile extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
SizedBox(
|
||||
height: 44,
|
||||
child: FilledButton(
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF2F9E94),
|
||||
foregroundColor: Colors.white,
|
||||
shape: const StadiumBorder(),
|
||||
textStyle: const TextStyle(fontWeight: FontWeight.w900),
|
||||
TapBounce(
|
||||
child: SizedBox(
|
||||
height: 44,
|
||||
child: FilledButton(
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF2F9E94),
|
||||
foregroundColor: Colors.white,
|
||||
shape: const StadiumBorder(),
|
||||
textStyle: const TextStyle(
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
child: const Text('Fechar'),
|
||||
),
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
child: const Text('Fechar'),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -12,10 +12,19 @@ class HelloSplashScreen extends StatefulWidget {
|
||||
State<HelloSplashScreen> createState() => _HelloSplashScreenState();
|
||||
}
|
||||
|
||||
class _HelloSplashScreenState extends State<HelloSplashScreen> with SingleTickerProviderStateMixin {
|
||||
class _HelloSplashScreenState extends State<HelloSplashScreen> with TickerProviderStateMixin {
|
||||
late final AnimationController _controller;
|
||||
late final Animation<double> _opacity;
|
||||
|
||||
late final AnimationController _popController = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 700),
|
||||
);
|
||||
late final Animation<double> _pop = CurvedAnimation(
|
||||
parent: _popController,
|
||||
curve: Curves.elasticOut,
|
||||
);
|
||||
|
||||
Timer? _fadeTimer;
|
||||
Timer? _doneTimer;
|
||||
|
||||
@@ -34,6 +43,7 @@ class _HelloSplashScreenState extends State<HelloSplashScreen> with SingleTicker
|
||||
);
|
||||
|
||||
_controller.value = 1.0;
|
||||
_popController.forward();
|
||||
|
||||
final int fadeMs = (widget.duration.inMilliseconds - 500).clamp(0, widget.duration.inMilliseconds);
|
||||
_fadeTimer = Timer(Duration(milliseconds: fadeMs), () {
|
||||
@@ -52,6 +62,7 @@ class _HelloSplashScreenState extends State<HelloSplashScreen> with SingleTicker
|
||||
_fadeTimer?.cancel();
|
||||
_doneTimer?.cancel();
|
||||
_controller.dispose();
|
||||
_popController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -70,15 +81,18 @@ class _HelloSplashScreenState extends State<HelloSplashScreen> with SingleTicker
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: const [
|
||||
Text(
|
||||
'Olá',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 64,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: Colors.white,
|
||||
height: 1.0,
|
||||
children: [
|
||||
ScaleTransition(
|
||||
scale: _pop,
|
||||
child: const Text(
|
||||
'Olá',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 64,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: Colors.white,
|
||||
height: 1.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import '../main.dart' show supabase;
|
||||
import '../widgets/app_dialogs.dart';
|
||||
import '../widgets/entrance.dart';
|
||||
import '../widgets/tap_bounce.dart';
|
||||
import 'terms_screen.dart';
|
||||
|
||||
const Color _teal = Color(0xFF2F9E94);
|
||||
@@ -65,53 +67,78 @@ class _SettingsBodyState extends State<SettingsBody> {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
_SectionLabel('Conta'),
|
||||
_SettingsCard(
|
||||
children: [
|
||||
_InfoTile(
|
||||
icon: Icons.person_outline_rounded,
|
||||
title: name.isEmpty ? 'Sem nome' : name,
|
||||
subtitle: email,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
_ActionTile(
|
||||
icon: Icons.logout_rounded,
|
||||
title: 'Sair',
|
||||
onTap: _signOut,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_SectionLabel('Sobre'),
|
||||
_SettingsCard(
|
||||
children: [
|
||||
_ActionTile(
|
||||
icon: Icons.description_outlined,
|
||||
title: 'Termos de Serviço',
|
||||
onTap: () => Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(builder: (_) => const TermsScreen()),
|
||||
FadeSlideIn(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_SectionLabel('Conta'),
|
||||
_SettingsCard(
|
||||
children: [
|
||||
_InfoTile(
|
||||
icon: Icons.person_outline_rounded,
|
||||
title: name.isEmpty ? 'Sem nome' : name,
|
||||
subtitle: email,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
_ActionTile(
|
||||
icon: Icons.logout_rounded,
|
||||
title: 'Sair',
|
||||
onTap: _signOut,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
const _InfoTile(
|
||||
icon: Icons.info_outline_rounded,
|
||||
title: 'Versão do app',
|
||||
subtitle: '1.0.0',
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_SectionLabel('Zona de risco'),
|
||||
_SettingsCard(
|
||||
children: [
|
||||
_ActionTile(
|
||||
icon: Icons.delete_forever_rounded,
|
||||
title: 'Apagar dados da conta',
|
||||
titleColor: _accentPink,
|
||||
loading: _deletingAccount,
|
||||
onTap: _deletingAccount ? null : _confirmDeleteAccountData,
|
||||
),
|
||||
],
|
||||
FadeSlideIn(
|
||||
delay: const Duration(milliseconds: 80),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_SectionLabel('Sobre'),
|
||||
_SettingsCard(
|
||||
children: [
|
||||
_ActionTile(
|
||||
icon: Icons.description_outlined,
|
||||
title: 'Termos de Serviço',
|
||||
onTap: () => Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => const TermsScreen(),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
const _InfoTile(
|
||||
icon: Icons.info_outline_rounded,
|
||||
title: 'Versão do app',
|
||||
subtitle: '1.0.0',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
FadeSlideIn(
|
||||
delay: const Duration(milliseconds: 160),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_SectionLabel('Zona de risco'),
|
||||
_SettingsCard(
|
||||
children: [
|
||||
_ActionTile(
|
||||
icon: Icons.delete_forever_rounded,
|
||||
title: 'Apagar dados da conta',
|
||||
titleColor: _accentPink,
|
||||
loading: _deletingAccount,
|
||||
onTap: _deletingAccount ? null : _confirmDeleteAccountData,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
@@ -193,20 +220,23 @@ class _ActionTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: Icon(icon, color: titleColor ?? _teal),
|
||||
title: Text(
|
||||
title,
|
||||
style: TextStyle(fontWeight: FontWeight.w800, color: titleColor),
|
||||
return TapBounce(
|
||||
scale: 0.98,
|
||||
child: ListTile(
|
||||
leading: Icon(icon, color: titleColor ?? _teal),
|
||||
title: Text(
|
||||
title,
|
||||
style: TextStyle(fontWeight: FontWeight.w800, color: titleColor),
|
||||
),
|
||||
trailing: loading
|
||||
? const SizedBox(
|
||||
width: 18,
|
||||
height: 18,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
: const Icon(Icons.chevron_right_rounded),
|
||||
onTap: onTap,
|
||||
),
|
||||
trailing: loading
|
||||
? const SizedBox(
|
||||
width: 18,
|
||||
height: 18,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
: const Icon(Icons.chevron_right_rounded),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import 'package:lottie/lottie.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
|
||||
|
||||
import '../widgets/entrance.dart';
|
||||
import '../widgets/tap_bounce.dart';
|
||||
|
||||
// Video data structure - easily editable for future updates.
|
||||
// Episódios 1-7 tocam via YouTube (não listado); preencha youtubeId ao subir
|
||||
// cada vídeo. Episódios 8-13 continuam embutidos no app (assets/videos).
|
||||
@@ -276,8 +279,13 @@ class _VideoScreenState extends State<VideoScreen> {
|
||||
),
|
||||
itemCount: _filteredVideos.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _VideoButton(
|
||||
video: _filteredVideos[index],
|
||||
return FadeSlideIn(
|
||||
delay: Duration(
|
||||
milliseconds: 40 * (index % 8),
|
||||
),
|
||||
child: _VideoButton(
|
||||
video: _filteredVideos[index],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -437,7 +445,9 @@ class _VideoButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
return TapBounce(
|
||||
scale: 0.95,
|
||||
child: Material(
|
||||
elevation: 8,
|
||||
shadowColor: Colors.black.withValues(alpha: 0.12),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
@@ -484,6 +494,7 @@ class _VideoButton extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user