espero que nao presisse mudar.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
import '../utils/session_manager.dart';
|
||||||
import '../models/game_model.dart';
|
import '../models/game_model.dart';
|
||||||
|
|
||||||
class GameController {
|
class GameController {
|
||||||
@@ -53,6 +54,9 @@ class GameController {
|
|||||||
// CRIAR JOGO
|
// CRIAR JOGO
|
||||||
Future<String?> createGame(String myTeam, String opponent, String season) async {
|
Future<String?> createGame(String myTeam, String opponent, String season) async {
|
||||||
try {
|
try {
|
||||||
|
// Marca que existe uma sessão/jogo em progresso localmente
|
||||||
|
// (será limpa quando o jogo terminar ou em falha)
|
||||||
|
await SessionManager.setInProgress(true);
|
||||||
final response = await _supabase.from('games').insert({
|
final response = await _supabase.from('games').insert({
|
||||||
'user_id': myUserId,
|
'user_id': myUserId,
|
||||||
'my_team': myTeam,
|
'my_team': myTeam,
|
||||||
@@ -77,6 +81,10 @@ class GameController {
|
|||||||
return response['id']?.toString();
|
return response['id']?.toString();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("Erro ao criar jogo: $e");
|
print("Erro ao criar jogo: $e");
|
||||||
|
// Se houve erro, limpa o flag para não exigir logout indevido
|
||||||
|
try {
|
||||||
|
await SessionManager.clear();
|
||||||
|
} catch (_) {}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart'; // Para as orientações
|
import 'package:flutter/services.dart'; // Para as orientações
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
import 'package:playmaker/classe/theme.dart';
|
import 'package:playmaker/classe/theme.dart';
|
||||||
import 'pages/login.dart';
|
import 'pages/login.dart';
|
||||||
|
import 'utils/session_manager.dart';
|
||||||
|
|
||||||
// Variável global para controlar o Tema
|
// Variável global para controlar o Tema
|
||||||
final ValueNotifier<ThemeMode> themeNotifier = ValueNotifier(ThemeMode.system);
|
final ValueNotifier<ThemeMode> themeNotifier = ValueNotifier(ThemeMode.system);
|
||||||
@@ -25,9 +26,41 @@ void main() async {
|
|||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatefulWidget {
|
||||||
const MyApp({super.key});
|
const MyApp({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MyApp> createState() => _MyAppState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeAppLifecycleState(AppLifecycleState state) async {
|
||||||
|
super.didChangeAppLifecycleState(state);
|
||||||
|
// Quando a app for para background/terminar, se houver sessão em progresso, desliga a sessão
|
||||||
|
if (state == AppLifecycleState.paused || state == AppLifecycleState.detached) {
|
||||||
|
final inProgress = await SessionManager.isInProgress();
|
||||||
|
if (inProgress) {
|
||||||
|
try {
|
||||||
|
await Supabase.instance.client.auth.signOut();
|
||||||
|
await SessionManager.clear();
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ValueListenableBuilder<ThemeMode>(
|
return ValueListenableBuilder<ThemeMode>(
|
||||||
|
|||||||
@@ -677,74 +677,73 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget mainContent = Column(
|
final Widget teamSelector = InkWell(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
onTap: () => _showTeamSelector(context),
|
||||||
children: [
|
child: Container(
|
||||||
InkWell(
|
padding: EdgeInsets.all(12 * context.sf),
|
||||||
onTap: () => _showTeamSelector(context),
|
decoration: BoxDecoration(
|
||||||
child: Container(
|
color: Theme.of(context).cardTheme.color,
|
||||||
padding: EdgeInsets.all(12 * context.sf),
|
borderRadius: BorderRadius.circular(15 * context.sf),
|
||||||
decoration: BoxDecoration(
|
border: Border.all(color: Colors.grey.withOpacity(0.2)),
|
||||||
color: Theme.of(context).cardTheme.color,
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(15 * context.sf),
|
|
||||||
border:
|
|
||||||
Border.all(color: Colors.grey.withOpacity(0.2)),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Row(children: [
|
|
||||||
(_selectedTeamLogo != null &&
|
|
||||||
_selectedTeamLogo!.isNotEmpty)
|
|
||||||
? ClipOval(
|
|
||||||
child: CachedNetworkImage(
|
|
||||||
imageUrl: _selectedTeamLogo!,
|
|
||||||
width: 24 * context.sf,
|
|
||||||
height: 24 * context.sf,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
placeholder: (context, url) => Icon(
|
|
||||||
Icons.shield,
|
|
||||||
color: AppTheme.primaryRed,
|
|
||||||
size: 24 * context.sf),
|
|
||||||
errorWidget:
|
|
||||||
(context, url, error) => Icon(
|
|
||||||
Icons.shield,
|
|
||||||
color: AppTheme.primaryRed,
|
|
||||||
size: 24 * context.sf),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Icon(Icons.shield,
|
|
||||||
color: AppTheme.primaryRed,
|
|
||||||
size: 24 * context.sf),
|
|
||||||
SizedBox(width: 10 * context.sf),
|
|
||||||
Text(_selectedTeamName,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16 * context.sf,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: textColor)),
|
|
||||||
]),
|
|
||||||
Icon(Icons.arrow_drop_down, color: textColor),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(height: 20 * context.sf),
|
child: Row(
|
||||||
if (!isWide) ...[
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(children: [
|
||||||
|
(_selectedTeamLogo != null && _selectedTeamLogo!.isNotEmpty)
|
||||||
|
? ClipOval(
|
||||||
|
child: CachedNetworkImage(
|
||||||
|
imageUrl: _selectedTeamLogo!,
|
||||||
|
width: 24 * context.sf,
|
||||||
|
height: 24 * context.sf,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
placeholder: (context, url) => Icon(
|
||||||
|
Icons.shield,
|
||||||
|
color: AppTheme.primaryRed,
|
||||||
|
size: 24 * context.sf),
|
||||||
|
errorWidget: (context, url, error) => Icon(
|
||||||
|
Icons.shield,
|
||||||
|
color: AppTheme.primaryRed,
|
||||||
|
size: 24 * context.sf),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Icon(Icons.shield, color: AppTheme.primaryRed, size: 24 * context.sf),
|
||||||
|
SizedBox(width: 10 * context.sf),
|
||||||
|
Text(_selectedTeamName,
|
||||||
|
style: TextStyle(fontSize: 16 * context.sf, fontWeight: FontWeight.bold, color: textColor)),
|
||||||
|
]),
|
||||||
|
Icon(Icons.arrow_drop_down, color: textColor),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget mainContent;
|
||||||
|
if (isWide) {
|
||||||
|
mainContent = Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
teamSelector,
|
||||||
|
SizedBox(height: 20 * context.sf),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(flex: 5, child: statsSection),
|
||||||
|
SizedBox(width: 20 * context.sf),
|
||||||
|
Expanded(flex: 6, child: historySection),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
mainContent = Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
teamSelector,
|
||||||
|
SizedBox(height: 20 * context.sf),
|
||||||
statsSection,
|
statsSection,
|
||||||
SizedBox(height: 40 * context.sf),
|
SizedBox(height: 40 * context.sf),
|
||||||
historySection,
|
historySection,
|
||||||
]
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isWide) {
|
|
||||||
mainContent = Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Expanded(flex: 5, child: statsSection),
|
|
||||||
SizedBox(width: 20 * context.sf),
|
|
||||||
Expanded(flex: 6, child: historySection),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1116,4 +1115,4 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
20
lib/utils/session_manager.dart
Normal file
20
lib/utils/session_manager.dart
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
class SessionManager {
|
||||||
|
static const _key = 'session_in_progress';
|
||||||
|
|
||||||
|
static Future<void> setInProgress(bool v) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setBool(_key, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<bool> isInProgress() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.getBool(_key) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> clear() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.remove(_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user