Auto-sync: 20260312_210001
This commit is contained in:
parent
99ae270818
commit
7c7bf0ef2d
15 changed files with 325 additions and 8 deletions
BIN
.DS_Store
vendored
BIN
.DS_Store
vendored
Binary file not shown.
2
.firebase/hosting.cHVibGlj.cache
Normal file
2
.firebase/hosting.cHVibGlj.cache
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
index.html,1773344753424,0d5d4b835a7d632ad11d249230a15561286f2bfcd1da8305c6fb294d37e5da09
|
||||||
|
404.html,1773344753356,05cbc6f94d7a69ce2e29646eab13be2c884e61ba93e3094df5028866876d18b3
|
||||||
5
.firebaserc
Normal file
5
.firebaserc
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"default": "tetraq-32a4a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1,47 @@
|
||||||
{"flutter":{"platforms":{"android":{"default":{"projectId":"tetraq-32a4a","appId":"1:705460445314:android:ceac21bb06b7a9f07b949b","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"tetraq-32a4a","appId":"1:705460445314:ios:54d64cb7592954327b949b","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"macos":{"default":{"projectId":"tetraq-32a4a","appId":"1:705460445314:ios:da11cbca5d1f6bc27b949b","uploadDebugSymbols":false,"fileOutput":"macos/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"tetraq-32a4a","configurations":{"android":"1:705460445314:android:ceac21bb06b7a9f07b949b","ios":"1:705460445314:ios:54d64cb7592954327b949b","macos":"1:705460445314:ios:da11cbca5d1f6bc27b949b"}}}}}}
|
{
|
||||||
|
"flutter": {
|
||||||
|
"platforms": {
|
||||||
|
"android": {
|
||||||
|
"default": {
|
||||||
|
"projectId": "tetraq-32a4a",
|
||||||
|
"appId": "1:705460445314:android:ceac21bb06b7a9f07b949b",
|
||||||
|
"fileOutput": "android/app/google-services.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ios": {
|
||||||
|
"default": {
|
||||||
|
"projectId": "tetraq-32a4a",
|
||||||
|
"appId": "1:705460445314:ios:54d64cb7592954327b949b",
|
||||||
|
"uploadDebugSymbols": false,
|
||||||
|
"fileOutput": "ios/Runner/GoogleService-Info.plist"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"macos": {
|
||||||
|
"default": {
|
||||||
|
"projectId": "tetraq-32a4a",
|
||||||
|
"appId": "1:705460445314:ios:da11cbca5d1f6bc27b949b",
|
||||||
|
"uploadDebugSymbols": false,
|
||||||
|
"fileOutput": "macos/Runner/GoogleService-Info.plist"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dart": {
|
||||||
|
"lib/firebase_options.dart": {
|
||||||
|
"projectId": "tetraq-32a4a",
|
||||||
|
"configurations": {
|
||||||
|
"android": "1:705460445314:android:ceac21bb06b7a9f07b949b",
|
||||||
|
"ios": "1:705460445314:ios:54d64cb7592954327b949b",
|
||||||
|
"macos": "1:705460445314:ios:da11cbca5d1f6bc27b949b"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hosting": {
|
||||||
|
"public": "public",
|
||||||
|
"ignore": [
|
||||||
|
"firebase.json",
|
||||||
|
"**/.*",
|
||||||
|
"**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
BIN
ios/.DS_Store
vendored
BIN
ios/.DS_Store
vendored
Binary file not shown.
|
|
@ -52,6 +52,7 @@
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
4867B86862DC650EC26D5F9C /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
4867B86862DC650EC26D5F9C /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
52CB81B72F635109004C3F43 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
5C30E1EF56D9EC1CAEADBE23 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
5C30E1EF56D9EC1CAEADBE23 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -146,6 +147,7 @@
|
||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
52CB81B72F635109004C3F43 /* Runner.entitlements */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||||
|
|
@ -473,6 +475,9 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = 2BX6QRR7GG;
|
DEVELOPMENT_TEAM = 2BX6QRR7GG;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
|
|
@ -485,6 +490,7 @@
|
||||||
MARKETING_VERSION = 1.0.2;
|
MARKETING_VERSION = 1.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
|
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
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;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
|
@ -658,6 +664,9 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = 2BX6QRR7GG;
|
DEVELOPMENT_TEAM = 2BX6QRR7GG;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
|
|
@ -670,6 +679,7 @@
|
||||||
MARKETING_VERSION = 1.0.2;
|
MARKETING_VERSION = 1.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
|
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
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";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|
@ -683,6 +693,9 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = 2BX6QRR7GG;
|
DEVELOPMENT_TEAM = 2BX6QRR7GG;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
|
|
@ -695,6 +708,7 @@
|
||||||
MARKETING_VERSION = 1.0.2;
|
MARKETING_VERSION = 1.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
|
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
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;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,19 @@
|
||||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>com.sanza.tetraq</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>tetraq</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
|
|
||||||
10
ios/Runner/Runner.entitlements
Normal file
10
ios/Runner/Runner.entitlements
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>applinks:tetraq-32a4a.web.app</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
@ -50,6 +50,12 @@ class GameController extends ChangeNotifier {
|
||||||
bool opponentWantsRematch = false;
|
bool opponentWantsRematch = false;
|
||||||
int lastMatchXP = 0;
|
int lastMatchXP = 0;
|
||||||
|
|
||||||
|
// --- VARIABILI PER IL LEVEL UP ---
|
||||||
|
bool hasLeveledUp = false;
|
||||||
|
int newlyReachedLevel = 1;
|
||||||
|
List<String> unlockedFeatures = [];
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
bool isSetupPhase = true;
|
bool isSetupPhase = true;
|
||||||
bool myJokerPlaced = false;
|
bool myJokerPlaced = false;
|
||||||
bool oppJokerPlaced = false;
|
bool oppJokerPlaced = false;
|
||||||
|
|
@ -81,6 +87,10 @@ class GameController extends ChangeNotifier {
|
||||||
_hasSavedResult = false;
|
_hasSavedResult = false;
|
||||||
lastMatchXP = 0;
|
lastMatchXP = 0;
|
||||||
|
|
||||||
|
// Reset Level Up vars
|
||||||
|
hasLeveledUp = false;
|
||||||
|
unlockedFeatures.clear();
|
||||||
|
|
||||||
myReaction = null;
|
myReaction = null;
|
||||||
opponentReaction = null;
|
opponentReaction = null;
|
||||||
_lastOpponentReactionTime = null;
|
_lastOpponentReactionTime = null;
|
||||||
|
|
@ -503,6 +513,22 @@ class GameController extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- LOGICA LEVEL UP E SBLOCCHI ---
|
||||||
|
List<String> _getUnlocks(int oldLevel, int newLevel) {
|
||||||
|
List<String> unlocks = [];
|
||||||
|
for(int i = oldLevel + 1; i <= newLevel; i++) {
|
||||||
|
if (i == 3) unlocks.add("Tema: Legno & Fiammiferi");
|
||||||
|
if (i == 5) unlocks.add("Tema: Quaderno (Doodle)");
|
||||||
|
if (i == 7) unlocks.add("Tema: Cyberpunk");
|
||||||
|
if (i == 10) {
|
||||||
|
unlocks.add("Tema: 8-Bit Arcade");
|
||||||
|
unlocks.add("Forma Arena: Caos");
|
||||||
|
}
|
||||||
|
if (i == 15) unlocks.add("Tema: Grimorio");
|
||||||
|
}
|
||||||
|
return unlocks;
|
||||||
|
}
|
||||||
|
|
||||||
void _saveMatchResult() {
|
void _saveMatchResult() {
|
||||||
if (_hasSavedResult) return;
|
if (_hasSavedResult) return;
|
||||||
_hasSavedResult = true;
|
_hasSavedResult = true;
|
||||||
|
|
@ -512,6 +538,8 @@ class GameController extends ChangeNotifier {
|
||||||
String myRealName = StorageService.instance.playerName;
|
String myRealName = StorageService.instance.playerName;
|
||||||
if (myRealName.isEmpty) myRealName = "IO";
|
if (myRealName.isEmpty) myRealName = "IO";
|
||||||
|
|
||||||
|
int oldLevel = StorageService.instance.playerLevel; // Salviamo il vecchio livello
|
||||||
|
|
||||||
if (isOnline) {
|
if (isOnline) {
|
||||||
bool isWin = isHost ? board.scoreRed > board.scoreBlue : board.scoreBlue > board.scoreRed;
|
bool isWin = isHost ? board.scoreRed > board.scoreBlue : board.scoreBlue > board.scoreRed;
|
||||||
calculatedXP = isWin ? 20 : (isDraw ? 5 : 2);
|
calculatedXP = isWin ? 20 : (isDraw ? 5 : 2);
|
||||||
|
|
@ -520,7 +548,7 @@ class GameController extends ChangeNotifier {
|
||||||
int oppScore = isHost ? board.scoreBlue : board.scoreRed;
|
int oppScore = isHost ? board.scoreBlue : board.scoreRed;
|
||||||
StorageService.instance.saveMatchToHistory(myName: myRealName, opponent: oppName, myScore: myScore, oppScore: oppScore, isOnline: true);
|
StorageService.instance.saveMatchToHistory(myName: myRealName, opponent: oppName, myScore: myScore, oppScore: oppScore, isOnline: true);
|
||||||
|
|
||||||
if (isWin) StorageService.instance.updateQuestProgress(0, 1); // Missione: Vinci Online
|
if (isWin) StorageService.instance.updateQuestProgress(0, 1);
|
||||||
|
|
||||||
} else if (isVsCPU) {
|
} else if (isVsCPU) {
|
||||||
int myScore = board.scoreRed; int cpuScore = board.scoreBlue;
|
int myScore = board.scoreRed; int cpuScore = board.scoreBlue;
|
||||||
|
|
@ -529,7 +557,7 @@ class GameController extends ChangeNotifier {
|
||||||
|
|
||||||
if (isWin) {
|
if (isWin) {
|
||||||
StorageService.instance.addWin();
|
StorageService.instance.addWin();
|
||||||
StorageService.instance.updateQuestProgress(1, 1); // Missione: Vinci vs CPU
|
StorageService.instance.updateQuestProgress(1, 1);
|
||||||
} else if (cpuScore > myScore) {
|
} else if (cpuScore > myScore) {
|
||||||
StorageService.instance.addLoss();
|
StorageService.instance.addLoss();
|
||||||
}
|
}
|
||||||
|
|
@ -539,12 +567,22 @@ class GameController extends ChangeNotifier {
|
||||||
StorageService.instance.saveMatchToHistory(myName: myRealName, opponent: "Ospite (Locale)", myScore: board.scoreRed, oppScore: board.scoreBlue, isOnline: false);
|
StorageService.instance.saveMatchToHistory(myName: myRealName, opponent: "Ospite (Locale)", myScore: board.scoreRed, oppScore: board.scoreBlue, isOnline: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Se si sta giocando in una forma speciale (non classica)
|
|
||||||
if (board.shape != ArenaShape.classic) {
|
if (board.shape != ArenaShape.classic) {
|
||||||
StorageService.instance.updateQuestProgress(2, 1); // Missione: Usa forme speciali
|
StorageService.instance.updateQuestProgress(2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastMatchXP = calculatedXP; StorageService.instance.addXP(calculatedXP); notifyListeners();
|
lastMatchXP = calculatedXP;
|
||||||
|
StorageService.instance.addXP(calculatedXP);
|
||||||
|
|
||||||
|
// --- CONTROLLO LEVEL UP DOPO AVER DATO GLI XP ---
|
||||||
|
int newLevel = StorageService.instance.playerLevel;
|
||||||
|
if (newLevel > oldLevel) {
|
||||||
|
hasLeveledUp = true;
|
||||||
|
newlyReachedLevel = newLevel;
|
||||||
|
unlockedFeatures = _getUnlocks(oldLevel, newLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void increaseLevelAndRestart() {
|
void increaseLevelAndRestart() {
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,10 @@ class MultiplayerService {
|
||||||
}
|
}
|
||||||
|
|
||||||
void shareInviteLink(String roomCode) {
|
void shareInviteLink(String roomCode) {
|
||||||
String message = "Ehi! Giochiamo a TetraQ? 🎮\nCopia questo intero messaggio e apri l'app per entrare direttamente, oppure inserisci manualmente il codice: $roomCode";
|
String message = "Ehi! Giochiamo a TetraQ? 🎮\n\n"
|
||||||
|
"Clicca su questo link per entrare direttamente in stanza:\n"
|
||||||
|
"tetraq://join?code=$roomCode\n\n"
|
||||||
|
"Oppure apri l'app e inserisci manualmente il codice: $roomCode";
|
||||||
Share.share(message);
|
Share.share(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ 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';
|
import '../admin/admin_screen.dart';
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:app_links/app_links.dart';
|
||||||
|
|
||||||
TextStyle _getTextStyle(AppThemeType themeType, TextStyle baseStyle) {
|
TextStyle _getTextStyle(AppThemeType themeType, TextStyle baseStyle) {
|
||||||
if (themeType == AppThemeType.doodle) {
|
if (themeType == AppThemeType.doodle) {
|
||||||
|
|
@ -391,20 +393,25 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
|
||||||
|
|
||||||
int _debugTapCount = 0;
|
int _debugTapCount = 0;
|
||||||
|
|
||||||
|
late AppLinks _appLinks;
|
||||||
|
StreamSubscription<Uri>? _linkSubscription;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
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!
|
StorageService.instance.syncLeaderboard();
|
||||||
});
|
});
|
||||||
_checkClipboardForInvite();
|
_checkClipboardForInvite();
|
||||||
|
_initDeepLinks(); // <--- AGGIUNGI QUESTO
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
|
_linkSubscription?.cancel(); // <--- AGGIUNGI QUESTO
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -534,6 +541,44 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- LOGICA DEEP LINKS ---
|
||||||
|
Future<void> _initDeepLinks() async {
|
||||||
|
_appLinks = AppLinks();
|
||||||
|
|
||||||
|
// 1. Controlla se l'app è stata aperta DA CHIUSA tramite un link
|
||||||
|
try {
|
||||||
|
final initialUri = await _appLinks.getInitialLink(); // <--- ECCO LA PAROLA CORRETTA!
|
||||||
|
if (initialUri != null) {
|
||||||
|
_handleDeepLink(initialUri);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("Errore lettura link iniziale: $e");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Rimane in ascolto se l'app era IN BACKGROUND
|
||||||
|
_linkSubscription = _appLinks.uriLinkStream.listen((uri) {
|
||||||
|
_handleDeepLink(uri);
|
||||||
|
}, onError: (err) {
|
||||||
|
debugPrint("Errore stream link: $err");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleDeepLink(Uri uri) {
|
||||||
|
debugPrint("Link ricevuto: $uri");
|
||||||
|
if (uri.scheme == 'tetraq' && uri.host == 'join') {
|
||||||
|
String? code = uri.queryParameters['code'];
|
||||||
|
if (code != null && code.length == 5) {
|
||||||
|
// Usa un piccolo delay per assicurarsi che l'app sia pronta
|
||||||
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
|
if (mounted) {
|
||||||
|
_promptJoinRoom(code.toUpperCase());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
Future<void> _checkClipboardForInvite() async {
|
Future<void> _checkClipboardForInvite() async {
|
||||||
try {
|
try {
|
||||||
ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
|
ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
|
||||||
|
|
|
||||||
33
public/404.html
Normal file
33
public/404.html
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Page Not Found</title>
|
||||||
|
|
||||||
|
<style media="screen">
|
||||||
|
body { background: #ECEFF1; color: rgba(0,0,0,0.87); font-family: Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 0; }
|
||||||
|
#message { background: white; max-width: 360px; margin: 100px auto 16px; padding: 32px 24px 16px; border-radius: 3px; }
|
||||||
|
#message h3 { color: #888; font-weight: normal; font-size: 16px; margin: 16px 0 12px; }
|
||||||
|
#message h2 { color: #ffa100; font-weight: bold; font-size: 16px; margin: 0 0 8px; }
|
||||||
|
#message h1 { font-size: 22px; font-weight: 300; color: rgba(0,0,0,0.6); margin: 0 0 16px;}
|
||||||
|
#message p { line-height: 140%; margin: 16px 0 24px; font-size: 14px; }
|
||||||
|
#message a { display: block; text-align: center; background: #039be5; text-transform: uppercase; text-decoration: none; color: white; padding: 16px; border-radius: 4px; }
|
||||||
|
#message, #message a { box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); }
|
||||||
|
#load { color: rgba(0,0,0,0.4); text-align: center; font-size: 13px; }
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
body, #message { margin-top: 0; background: white; box-shadow: none; }
|
||||||
|
body { border-top: 16px solid #ffa100; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="message">
|
||||||
|
<h2>404</h2>
|
||||||
|
<h1>Page Not Found</h1>
|
||||||
|
<p>The specified file was not found on this website. Please check the URL for mistakes and try again.</p>
|
||||||
|
<h3>Why am I seeing this?</h3>
|
||||||
|
<p>This page was generated by the Firebase Command-Line Interface. To modify it, edit the <code>404.html</code> file in your project's configured <code>public</code> directory.</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
89
public/index.html
Normal file
89
public/index.html
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Welcome to Firebase Hosting</title>
|
||||||
|
|
||||||
|
<!-- update the version number as needed -->
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-app-compat.js"></script>
|
||||||
|
<!-- include only the Firebase features as you need -->
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-auth-compat.js"></script>
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-database-compat.js"></script>
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-firestore-compat.js"></script>
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-functions-compat.js"></script>
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-messaging-compat.js"></script>
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-storage-compat.js"></script>
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-analytics-compat.js"></script>
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-remote-config-compat.js"></script>
|
||||||
|
<script defer src="/__/firebase/12.10.0/firebase-performance-compat.js"></script>
|
||||||
|
<!--
|
||||||
|
initialize the SDK after all desired features are loaded, set useEmulator to false
|
||||||
|
to avoid connecting the SDK to running emulators.
|
||||||
|
-->
|
||||||
|
<script defer src="/__/firebase/init.js?useEmulator=true"></script>
|
||||||
|
|
||||||
|
<style media="screen">
|
||||||
|
body { background: #ECEFF1; color: rgba(0,0,0,0.87); font-family: Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 0; }
|
||||||
|
#message { background: white; max-width: 360px; margin: 100px auto 16px; padding: 32px 24px; border-radius: 3px; }
|
||||||
|
#message h2 { color: #ffa100; font-weight: bold; font-size: 16px; margin: 0 0 8px; }
|
||||||
|
#message h1 { font-size: 22px; font-weight: 300; color: rgba(0,0,0,0.6); margin: 0 0 16px;}
|
||||||
|
#message p { line-height: 140%; margin: 16px 0 24px; font-size: 14px; }
|
||||||
|
#message a { display: block; text-align: center; background: #039be5; text-transform: uppercase; text-decoration: none; color: white; padding: 16px; border-radius: 4px; }
|
||||||
|
#message, #message a { box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); }
|
||||||
|
#load { color: rgba(0,0,0,0.4); text-align: center; font-size: 13px; }
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
body, #message { margin-top: 0; background: white; box-shadow: none; }
|
||||||
|
body { border-top: 16px solid #ffa100; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="message">
|
||||||
|
<h2>Welcome</h2>
|
||||||
|
<h1>Firebase Hosting Setup Complete</h1>
|
||||||
|
<p>You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!</p>
|
||||||
|
<a target="_blank" href="https://firebase.google.com/docs/hosting/">Open Hosting Documentation</a>
|
||||||
|
</div>
|
||||||
|
<p id="load">Firebase SDK Loading…</p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const loadEl = document.querySelector('#load');
|
||||||
|
// // 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
||||||
|
// // The Firebase SDK is initialized and available here!
|
||||||
|
//
|
||||||
|
// firebase.auth().onAuthStateChanged(user => { });
|
||||||
|
// firebase.database().ref('/path/to/ref').on('value', snapshot => { });
|
||||||
|
// firebase.firestore().doc('/foo/bar').get().then(() => { });
|
||||||
|
// firebase.functions().httpsCallable('yourFunction')().then(() => { });
|
||||||
|
// firebase.messaging().requestPermission().then(() => { });
|
||||||
|
// firebase.storage().ref('/path/to/ref').getDownloadURL().then(() => { });
|
||||||
|
// firebase.analytics(); // call to activate
|
||||||
|
// firebase.analytics().logEvent('tutorial_completed');
|
||||||
|
// firebase.performance(); // call to activate
|
||||||
|
//
|
||||||
|
// // 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
||||||
|
|
||||||
|
try {
|
||||||
|
let app = firebase.app();
|
||||||
|
let features = [
|
||||||
|
'auth',
|
||||||
|
'database',
|
||||||
|
'firestore',
|
||||||
|
'functions',
|
||||||
|
'messaging',
|
||||||
|
'storage',
|
||||||
|
'analytics',
|
||||||
|
'remoteConfig',
|
||||||
|
'performance',
|
||||||
|
].filter(feature => typeof app[feature] === 'function');
|
||||||
|
loadEl.textContent = `Firebase SDK loaded with ${features.join(', ')}`;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
loadEl.textContent = 'Error loading the Firebase SDK, check the console.';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
11
tetraq_website/.well-known/apple-app-site-association
Normal file
11
tetraq_website/.well-known/apple-app-site-association
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"applinks": {
|
||||||
|
"apps": [],
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"appID": "2BX6QRR7GG.com.sanza.tetraq",
|
||||||
|
"paths": [ "/join" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
8
tetraq_website/.well-known/assetlinks.json
Normal file
8
tetraq_website/.well-known/assetlinks.json
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
[{
|
||||||
|
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||||
|
"target": {
|
||||||
|
"namespace": "android_app",
|
||||||
|
"package_name": "com.amastra.tetraq",
|
||||||
|
"sha256_cert_fingerprints": ["DA_INSERIRE_IN_FUTURO"]
|
||||||
|
}
|
||||||
|
}]
|
||||||
Loading…
Reference in a new issue