pdf e exel
This commit is contained in:
@@ -4,8 +4,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:playmaker/classe/theme.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart'; // 👇 IMPORTAÇÃO PARA CACHE
|
||||
import 'package:shared_preferences/shared_preferences.dart'; // 👇 IMPORTAÇÃO PARA MEMÓRIA RÁPIDA
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../utils/size_extension.dart';
|
||||
import 'login.dart';
|
||||
@@ -23,7 +23,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
File? _localImageFile;
|
||||
String? _uploadedImageUrl;
|
||||
bool _isUploadingImage = false;
|
||||
bool _isMemoryLoaded = false; // 👇 VARIÁVEL MÁGICA CONTRA O PISCAR
|
||||
bool _isMemoryLoaded = false;
|
||||
|
||||
final supabase = Supabase.instance.client;
|
||||
|
||||
@@ -33,16 +33,14 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
_loadUserAvatar();
|
||||
}
|
||||
|
||||
// 👇 LÊ A IMAGEM DA MEMÓRIA INSTANTANEAMENTE E CONFIRMA NA BD
|
||||
Future<void> _loadUserAvatar() async {
|
||||
// 1. Lê da memória rápida primeiro!
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final savedUrl = prefs.getString('meu_avatar_guardado');
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
if (savedUrl != null) _uploadedImageUrl = savedUrl;
|
||||
_isMemoryLoaded = true; // Avisa que já leu a memória
|
||||
_isMemoryLoaded = true;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -59,7 +57,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
if (mounted && data != null && data['avatar_url'] != null) {
|
||||
final urlDoSupabase = data['avatar_url'];
|
||||
|
||||
// Atualiza a memória se a foto na base de dados for diferente
|
||||
if (urlDoSupabase != savedUrl) {
|
||||
await prefs.setString('meu_avatar_guardado', urlDoSupabase);
|
||||
setState(() {
|
||||
@@ -68,7 +65,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print("Erro ao carregar avatar: $e");
|
||||
debugPrint("Erro ao carregar avatar: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +92,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
fileOptions: const FileOptions(cacheControl: '3600', upsert: true)
|
||||
);
|
||||
|
||||
final String publicUrl = supabase.storage.from('avatars').getPublicUrl(storagePath);
|
||||
// 👇 TRUQUE MÁGICO PARA O AVATAR ATUALIZAR: Adicionar o timestamp ao URL!
|
||||
final String baseUrl = supabase.storage.from('avatars').getPublicUrl(storagePath);
|
||||
final String publicUrl = '$baseUrl?v=${DateTime.now().millisecondsSinceEpoch}';
|
||||
|
||||
await supabase
|
||||
.from('profiles')
|
||||
@@ -104,7 +103,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
'avatar_url': publicUrl
|
||||
});
|
||||
|
||||
// 👇 MÁGICA: GUARDA LOGO O NOVO URL NA MEMÓRIA PARA A HOME SABER!
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('meu_avatar_guardado', publicUrl);
|
||||
|
||||
@@ -280,7 +278,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
// 👇 AVATAR OTIMIZADO: SEM LAG, COM CACHE E MEMÓRIA
|
||||
Widget _buildTappableProfileAvatar(BuildContext context, Color primaryRed) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
@@ -298,29 +295,21 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
),
|
||||
child: ClipOval(
|
||||
child: _isUploadingImage && _localImageFile != null
|
||||
// 1. Mostrar imagem local (galeria) ENQUANTO está a fazer upload
|
||||
? Image.file(_localImageFile!, fit: BoxFit.cover)
|
||||
|
||||
// 2. Antes da memória carregar, fica só o fundo (evita piscar)
|
||||
: !_isMemoryLoaded
|
||||
? const SizedBox()
|
||||
|
||||
// 3. Depois da memória carregar, se houver URL, desenha com Cache!
|
||||
: _uploadedImageUrl != null && _uploadedImageUrl!.isNotEmpty
|
||||
? CachedNetworkImage(
|
||||
imageUrl: _uploadedImageUrl!,
|
||||
fit: BoxFit.cover,
|
||||
fadeInDuration: Duration.zero, // Fica instantâneo!
|
||||
fadeInDuration: Duration.zero,
|
||||
placeholder: (context, url) => const SizedBox(),
|
||||
errorWidget: (context, url, error) => Icon(Icons.person, color: primaryRed, size: 36 * context.sf),
|
||||
)
|
||||
|
||||
// 4. Se não houver URL, mete o boneco
|
||||
: Icon(Icons.person, color: primaryRed, size: 36 * context.sf),
|
||||
),
|
||||
),
|
||||
|
||||
// ÍCONE DE LÁPIS
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
@@ -335,7 +324,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
),
|
||||
),
|
||||
|
||||
// LOADING OVERLAY (Enquanto faz o upload)
|
||||
if (_isUploadingImage)
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
@@ -364,9 +352,15 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(backgroundColor: AppTheme.primaryRed, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))),
|
||||
onPressed: () async {
|
||||
// Limpa a memória do Avatar ao sair para não aparecer na conta de outra pessoa!
|
||||
// 👇 AGORA LIMPA A EQUIPA E TUDO DA MEMÓRIA AO SAIR!
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('meu_avatar_guardado');
|
||||
await prefs.remove('last_team_id');
|
||||
await prefs.remove('last_team_name');
|
||||
await prefs.remove('last_team_logo');
|
||||
await prefs.remove('last_team_wins');
|
||||
await prefs.remove('last_team_losses');
|
||||
await prefs.remove('last_team_draws');
|
||||
|
||||
await Supabase.instance.client.auth.signOut();
|
||||
if (ctx.mounted) {
|
||||
|
||||
Reference in New Issue
Block a user