Auto-sync: 20260312_150000
This commit is contained in:
parent
a84c0b51b0
commit
99ae270818
5 changed files with 143 additions and 11 deletions
BIN
ios/.DS_Store
vendored
BIN
ios/.DS_Store
vendored
Binary file not shown.
|
|
@ -483,7 +483,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.2;
|
MARKETING_VERSION = 1.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.amastra.tetraq;
|
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|
@ -668,7 +668,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.2;
|
MARKETING_VERSION = 1.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.amastra.tetraq;
|
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
|
@ -693,7 +693,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.2;
|
MARKETING_VERSION = 1.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.amastra.tetraq;
|
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
|
|
@ -24,6 +26,8 @@
|
||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
|
|
@ -41,9 +45,5 @@
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
|
||||||
<true/>
|
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
||||||
128
lib/ui/admin/admin_screen.dart
Normal file
128
lib/ui/admin/admin_screen.dart
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
// ===========================================================================
|
||||||
|
// FILE: lib/ui/admin/admin_screen.dart
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import '../../core/theme_manager.dart';
|
||||||
|
|
||||||
|
class AdminScreen extends StatelessWidget {
|
||||||
|
const AdminScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<ThemeManager>().currentColors;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: theme.background,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text("DASHBOARD ADMIN 🕵️♂️", style: TextStyle(color: theme.text, fontWeight: FontWeight.w900, letterSpacing: 2)),
|
||||||
|
backgroundColor: theme.background,
|
||||||
|
iconTheme: IconThemeData(color: theme.text),
|
||||||
|
elevation: 0,
|
||||||
|
),
|
||||||
|
body: StreamBuilder<QuerySnapshot>(
|
||||||
|
// Ordiniamo per Ultimo Accesso, così i giocatori attivi di recente sono in cima!
|
||||||
|
stream: FirebaseFirestore.instance.collection('leaderboard').orderBy('lastActive', descending: true).snapshots(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return Center(child: CircularProgressIndicator(color: theme.playerBlue));
|
||||||
|
}
|
||||||
|
if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
|
||||||
|
return Center(child: Text("Nessun giocatore trovato nel database.", style: TextStyle(color: theme.text)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var docs = snapshot.data!.docs;
|
||||||
|
|
||||||
|
return ListView.builder(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
itemCount: docs.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var data = docs[index].data() as Map<String, dynamic>;
|
||||||
|
|
||||||
|
String name = data['name'] ?? 'Fantasma';
|
||||||
|
int level = data['level'] ?? 1;
|
||||||
|
int xp = data['xp'] ?? 0;
|
||||||
|
int wins = data['wins'] ?? 0;
|
||||||
|
String platform = data['platform'] ?? 'Sconosciuta';
|
||||||
|
|
||||||
|
// Formattazione Date (Se esistono)
|
||||||
|
DateTime? created;
|
||||||
|
if (data['accountCreated'] != null) created = (data['accountCreated'] as Timestamp).toDate();
|
||||||
|
|
||||||
|
DateTime? lastActive;
|
||||||
|
if (data['lastActive'] != null) lastActive = (data['lastActive'] as Timestamp).toDate();
|
||||||
|
|
||||||
|
String createdStr = created != null ? DateFormat('dd MMM yyyy').format(created) : 'N/D';
|
||||||
|
String lastActiveStr = lastActive != null ? DateFormat('dd MMM yyyy - HH:mm').format(lastActive) : 'N/D';
|
||||||
|
|
||||||
|
IconData platformIcon = Icons.device_unknown;
|
||||||
|
if (platform == 'iOS') platformIcon = Icons.apple;
|
||||||
|
if (platform == 'Android') platformIcon = Icons.android;
|
||||||
|
|
||||||
|
return Card(
|
||||||
|
color: theme.text.withOpacity(0.05),
|
||||||
|
elevation: 0,
|
||||||
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
side: BorderSide(color: theme.gridLine.withOpacity(0.3))
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(name, style: TextStyle(color: theme.playerBlue, fontSize: 22, fontWeight: FontWeight.w900)),
|
||||||
|
Icon(platformIcon, color: theme.text.withOpacity(0.7)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text("Liv. $level", style: TextStyle(color: theme.playerRed, fontWeight: FontWeight.bold, fontSize: 16)),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Text("$xp XP", style: TextStyle(color: theme.text.withOpacity(0.7))),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Text("Vittorie: $wins", style: TextStyle(color: Colors.amber.shade700, fontWeight: FontWeight.bold)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Divider(),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Registrato il:", style: TextStyle(color: theme.text.withOpacity(0.5), fontSize: 10)),
|
||||||
|
Text(createdStr, style: TextStyle(color: theme.text, fontSize: 12, fontWeight: FontWeight.bold)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text("Ultimo Accesso:", style: TextStyle(color: theme.text.withOpacity(0.5), fontSize: 10)),
|
||||||
|
Text(lastActiveStr, style: TextStyle(color: Colors.green, fontSize: 12, fontWeight: FontWeight.bold)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,7 @@ import '../multiplayer/lobby_screen.dart';
|
||||||
import 'history_screen.dart';
|
import 'history_screen.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:tetraq/l10n/app_localizations.dart';
|
import 'package:tetraq/l10n/app_localizations.dart';
|
||||||
|
import '../admin/admin_screen.dart';
|
||||||
|
|
||||||
TextStyle _getTextStyle(AppThemeType themeType, TextStyle baseStyle) {
|
TextStyle _getTextStyle(AppThemeType themeType, TextStyle baseStyle) {
|
||||||
if (themeType == AppThemeType.doodle) {
|
if (themeType == AppThemeType.doodle) {
|
||||||
|
|
@ -396,6 +397,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_checkPlayerName();
|
_checkPlayerName();
|
||||||
|
StorageService.instance.syncLeaderboard(); // <--- AGGIUNTO: Segna l'ultimo accesso ORA!
|
||||||
});
|
});
|
||||||
_checkClipboardForInvite();
|
_checkClipboardForInvite();
|
||||||
}
|
}
|
||||||
|
|
@ -1233,20 +1235,22 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
|
||||||
// --- IL TRUCCO DELLO SVILUPPATORE PROTETTO ---
|
// --- IL TRUCCO DELLO SVILUPPATORE PROTETTO ---
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (kReleaseMode) return;
|
|
||||||
_debugTapCount++;
|
_debugTapCount++;
|
||||||
if (_debugTapCount >= 5) {
|
if (_debugTapCount == 5) {
|
||||||
_debugTapCount = 0;
|
|
||||||
StorageService.instance.addXP(2000);
|
StorageService.instance.addXP(2000);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text("🛠 DEBUG MODE: +20 Livelli! Tutto sbloccato.", style: _getTextStyle(themeType, const TextStyle(color: Colors.white, fontWeight: FontWeight.bold))),
|
content: Text("🛠 DEBUG MODE: +20 Livelli!", style: _getTextStyle(themeType, const TextStyle(color: Colors.white, fontWeight: FontWeight.bold))),
|
||||||
backgroundColor: Colors.purpleAccent,
|
backgroundColor: Colors.purpleAccent,
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
} else if (_debugTapCount >= 7) {
|
||||||
|
_debugTapCount = 0; // Resetta il contatore
|
||||||
|
// APRE LA DASHBOARD SEGRETA!
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (_) => const AdminScreen()));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue