Auto-sync: 20260305_150000

This commit is contained in:
Paolo 2026-03-05 15:00:00 +01:00
parent 434ea96444
commit b2b94a5e72
32 changed files with 1146 additions and 53 deletions

BIN
.DS_Store vendored

Binary file not shown.

View file

@ -9,7 +9,7 @@ plugins {
}
android {
namespace = "com.sanza.tetraq"
namespace = "com.amastra.tetraq"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
@ -24,7 +24,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.sanza.tetraq"
applicationId = "com.amastra.tetraq"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion

View file

@ -5,6 +5,25 @@
"storage_bucket": "tetraq-32a4a.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:705460445314:android:ceac21bb06b7a9f07b949b",
"android_client_info": {
"package_name": "com.amastra.tetraq"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyBsXO595xVITDPrRnXrW8HPQLOe7Rz4Gg4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:705460445314:android:4d35fef29cfd63727b949b",

View file

@ -1,4 +1,4 @@
package com.sanza.tetraq
package com.amastra.tetraq
import io.flutter.embedding.android.FlutterActivity

View file

@ -1 +1 @@
{"flutter":{"platforms":{"android":{"default":{"projectId":"tetraq-32a4a","appId":"1:705460445314:android:4d35fef29cfd63727b949b","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"tetraq-32a4a","appId":"1:705460445314:ios:da11cbca5d1f6bc27b949b","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:4d35fef29cfd63727b949b","ios":"1:705460445314:ios:da11cbca5d1f6bc27b949b","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"}}}}}}

27
genera_lingue.dart Normal file
View file

@ -0,0 +1,27 @@
import 'dart:io';
import 'dart:convert';
void main() async {
final dir = Directory('lib/l10n');
if (!await dir.exists()) await dir.create(recursive: true);
final Map<String, Map<String, String>> translations = {
'it': {"appTitle": "TetraQ", "welcomeTitle": "BENVENUTO IN TETRAQ!", "nameHint": "NOME", "saveAndPlay": "SALVA E GIOCA", "onlineTitle": "ONLINE", "onlineSub": "Sfida il mondo", "cpuTitle": "VS CPU", "cpuSub": "Allenati con l'IA", "localTitle": "LOCALE", "localSub": "Stesso schermo", "leaderboardTitle": "CLASSIFICA", "questsTitle": "SFIDE", "themesTitle": "TEMI", "tutorialTitle": "TUTORIAL", "startGame": "AVVIA PARTITA", "createMatch": "CREA PARTITA", "joinMatch": "UNISCITI", "gameOver": "FINE PARTITA", "mainMenu": "TORNA AL MENU", "exit": "ESCI"},
'en': {"appTitle": "TetraQ", "welcomeTitle": "WELCOME TO TETRAQ!", "nameHint": "NAME", "saveAndPlay": "SAVE & PLAY", "onlineTitle": "ONLINE", "onlineSub": "Challenge the world", "cpuTitle": "VS CPU", "cpuSub": "Train with AI", "localTitle": "LOCAL", "localSub": "Same screen", "leaderboardTitle": "LEADERBOARD", "questsTitle": "QUESTS", "themesTitle": "THEMES", "tutorialTitle": "TUTORIAL", "startGame": "START GAME", "createMatch": "CREATE MATCH", "joinMatch": "JOIN", "gameOver": "GAME OVER", "mainMenu": "BACK TO MENU", "exit": "EXIT"},
'es': {"appTitle": "TetraQ", "welcomeTitle": "¡BIENVENIDO A TETRAQ!", "nameHint": "NOMBRE", "saveAndPlay": "GUARDAR Y JUGAR", "onlineTitle": "ONLINE", "onlineSub": "Desafía al mundo", "cpuTitle": "VS CPU", "cpuSub": "Entrena con IA", "localTitle": "LOCAL", "localSub": "Misma pantalla", "leaderboardTitle": "RANKING", "questsTitle": "MISIONES", "themesTitle": "TEMAS", "tutorialTitle": "TUTORIAL", "startGame": "INICIAR JUEGO", "createMatch": "CREAR PARTIDA", "joinMatch": "UNIRSE", "gameOver": "FIN DEL JUEGO", "mainMenu": "VOLVER AL MENÚ", "exit": "SALIR"},
'fr': {"appTitle": "TetraQ", "welcomeTitle": "BIENVENUE DANS TETRAQ !", "nameHint": "NOM", "saveAndPlay": "SAUVEGARDER ET JOUER", "onlineTitle": "EN LIGNE", "onlineSub": "Défiez le monde", "cpuTitle": "VS CPU", "cpuSub": "Entraînez avec l'IA", "localTitle": "LOCAL", "localSub": "Même écran", "leaderboardTitle": "CLASSEMENT", "questsTitle": "QUÊTES", "themesTitle": "THÈMES", "tutorialTitle": "TUTORIEL", "startGame": "JOUER", "createMatch": "CRÉER UN MATCH", "joinMatch": "REJOINDRE", "gameOver": "FIN DE PARTIE", "mainMenu": "RETOUR AU MENU", "exit": "QUITTER"},
'de': {"appTitle": "TetraQ", "welcomeTitle": "WILLKOMMEN BEI TETRAQ!", "nameHint": "NAME", "saveAndPlay": "SPEICHERN & SPIELEN", "onlineTitle": "ONLINE", "onlineSub": "Fordere die Welt heraus", "cpuTitle": "VS CPU", "cpuSub": "Trainiere mit KI", "localTitle": "LOKAL", "localSub": "Gleicher Bildschirm", "leaderboardTitle": "RANGLISTE", "questsTitle": "MISSIONEN", "themesTitle": "THEMEN", "tutorialTitle": "TUTORIAL", "startGame": "SPIEL STARTEN", "createMatch": "SPIEL ERSTELLEN", "joinMatch": "BEITRETEN", "gameOver": "SPIELENDE", "mainMenu": "ZURÜCK ZUM MENÜ", "exit": "BEENDEN"},
'pt': {"appTitle": "TetraQ", "welcomeTitle": "BEM-VINDO AO TETRAQ!", "nameHint": "NOME", "saveAndPlay": "SALVAR E JOGAR", "onlineTitle": "ONLINE", "onlineSub": "Desafie o mundo", "cpuTitle": "VS CPU", "cpuSub": "Treine com a IA", "localTitle": "LOCAL", "localSub": "Mesma tela", "leaderboardTitle": "CLASSIFICAÇÃO", "questsTitle": "DESAFIOS", "themesTitle": "TEMAS", "tutorialTitle": "TUTORIAL", "startGame": "INICIAR JOGO", "createMatch": "CRIAR PARTIDA", "joinMatch": "ENTRAR", "gameOver": "FIM DE JOGO", "mainMenu": "VOLTAR AO MENU", "exit": "SAIR"},
'ru': {"appTitle": "TetraQ", "welcomeTitle": "ДОБРО ПОЖАЛОВАТЬ В TETRAQ!", "nameHint": "ИМЯ", "saveAndPlay": "СОХРАНИТЬ И ИГРАТЬ", "onlineTitle": "ОНЛАЙН", "onlineSub": "Брось вызов миру", "cpuTitle": "VS ИИ", "cpuSub": "Тренировка с ИИ", "localTitle": "ЛОКАЛЬНО", "localSub": "Один экран", "leaderboardTitle": "РЕЙТИНГ", "questsTitle": "ЗАДАНИЯ", "themesTitle": "ТЕМЫ", "tutorialTitle": "ОБУЧЕНИЕ", "startGame": "НАЧАТЬ ИГРУ", "createMatch": "СОЗДАТЬ ИГРУ", "joinMatch": "ПРИСОЕДИНИТЬСЯ", "gameOver": "ИГРА ОКОНЧЕНА", "mainMenu": "В ГЛАВНОЕ МЕНЮ", "exit": "ВЫХОД"},
'zh': {"appTitle": "TetraQ", "welcomeTitle": "欢迎来到 TETRAQ", "nameHint": "名字", "saveAndPlay": "保存并开始", "onlineTitle": "在线匹配", "onlineSub": "挑战世界", "cpuTitle": "人机对战", "cpuSub": "与AI训练", "localTitle": "本地游戏", "localSub": "同屏对战", "leaderboardTitle": "排行榜", "questsTitle": "任务", "themesTitle": "主题", "tutorialTitle": "教程", "startGame": "开始游戏", "createMatch": "创建比赛", "joinMatch": "加入", "gameOver": "游戏结束", "mainMenu": "返回主菜单", "exit": "退出"}
};
for (var lang in translations.keys) {
final file = File('lib/l10n/app_$lang.arb');
final Map<String, dynamic> finalContent = {"@@locale": lang, ...translations[lang]!};
await file.writeAsString(JsonEncoder.withIndent(' ').convert(finalContent));
}
// Crea anche il file di configurazione
await File('l10n.yaml').writeAsString("arb-dir: lib/l10n\ntemplate-arb-file: app_it.arb\noutput-localization-file: app_localizations.dart\n");
}

View file

@ -483,7 +483,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.2;
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
PRODUCT_BUNDLE_IDENTIFIER = com.amastra.tetraq;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@ -500,7 +500,7 @@
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq.RunnerTests;
PRODUCT_BUNDLE_IDENTIFIER = com.amastra.tetraq.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -518,7 +518,7 @@
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq.RunnerTests;
PRODUCT_BUNDLE_IDENTIFIER = com.amastra.tetraq.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -534,7 +534,7 @@
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq.RunnerTests;
PRODUCT_BUNDLE_IDENTIFIER = com.amastra.tetraq.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -668,7 +668,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.2;
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
PRODUCT_BUNDLE_IDENTIFIER = com.amastra.tetraq;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -693,7 +693,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.2;
PRODUCT_BUNDLE_IDENTIFIER = com.sanza.tetraq;
PRODUCT_BUNDLE_IDENTIFIER = com.amastra.tetraq;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;

View file

@ -9,7 +9,7 @@
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.sanza.tetraq</string>
<string>com.amastra.tetraq</string>
<key>PROJECT_ID</key>
<string>tetraq-32a4a</string>
<key>STORAGE_BUCKET</key>
@ -25,6 +25,6 @@
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:705460445314:ios:da11cbca5d1f6bc27b949b</string>
<string>1:705460445314:ios:54d64cb7592954327b949b</string>
</dict>
</plist>

4
l10n.yaml Normal file
View file

@ -0,0 +1,4 @@
arb-dir: lib/l10n
template-arb-file: app_it.arb
output-localization-file: app_localizations.dart
output-dir: lib/l10n

BIN
lib/.DS_Store vendored

Binary file not shown.

View file

@ -48,7 +48,7 @@ class DefaultFirebaseOptions {
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyBsXO595xVITDPrRnXrW8HPQLOe7Rz4Gg4',
appId: '1:705460445314:android:4d35fef29cfd63727b949b',
appId: '1:705460445314:android:ceac21bb06b7a9f07b949b',
messagingSenderId: '705460445314',
projectId: 'tetraq-32a4a',
storageBucket: 'tetraq-32a4a.firebasestorage.app',
@ -56,11 +56,11 @@ class DefaultFirebaseOptions {
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyB77j18Jgeb9gBAEwp-uyOQvr4m-RJ_rAE',
appId: '1:705460445314:ios:da11cbca5d1f6bc27b949b',
appId: '1:705460445314:ios:54d64cb7592954327b949b',
messagingSenderId: '705460445314',
projectId: 'tetraq-32a4a',
storageBucket: 'tetraq-32a4a.firebasestorage.app',
iosBundleId: 'com.sanza.tetraq',
iosBundleId: 'com.amastra.tetraq',
);
static const FirebaseOptions macos = FirebaseOptions(
@ -71,4 +71,5 @@ class DefaultFirebaseOptions {
storageBucket: 'tetraq-32a4a.firebasestorage.app',
iosBundleId: 'com.sanza.tetraq',
);
}
}

23
lib/l10n/app_de.arb Normal file
View file

@ -0,0 +1,23 @@
{
"@@locale": "de",
"appTitle": "TetraQ",
"welcomeTitle": "WILLKOMMEN BEI TETRAQ!",
"nameHint": "NAME",
"saveAndPlay": "SPEICHERN & SPIELEN",
"onlineTitle": "ONLINE",
"onlineSub": "Fordere die Welt heraus",
"cpuTitle": "VS CPU",
"cpuSub": "Trainiere mit KI",
"localTitle": "LOKAL",
"localSub": "Gleicher Bildschirm",
"leaderboardTitle": "RANGLISTE",
"questsTitle": "MISSIONEN",
"themesTitle": "THEMEN",
"tutorialTitle": "TUTORIAL",
"startGame": "SPIEL STARTEN",
"createMatch": "SPIEL ERSTELLEN",
"joinMatch": "BEITRETEN",
"gameOver": "SPIELENDE",
"mainMenu": "ZURÜCK ZUM MENÜ",
"exit": "BEENDEN"
}

View file

@ -1,4 +1,23 @@
{
"@@locale": "en",
"appTitle": "TetraQ",
"playLocal": "PASS & PLAY (Local)"
}
"welcomeTitle": "WELCOME TO TETRAQ!",
"nameHint": "NAME",
"saveAndPlay": "SAVE & PLAY",
"onlineTitle": "ONLINE",
"onlineSub": "Challenge the world",
"cpuTitle": "VS CPU",
"cpuSub": "Train with AI",
"localTitle": "LOCAL",
"localSub": "Same screen",
"leaderboardTitle": "LEADERBOARD",
"questsTitle": "QUESTS",
"themesTitle": "THEMES",
"tutorialTitle": "TUTORIAL",
"startGame": "START GAME",
"createMatch": "CREATE MATCH",
"joinMatch": "JOIN",
"gameOver": "GAME OVER",
"mainMenu": "BACK TO MENU",
"exit": "EXIT"
}

23
lib/l10n/app_es.arb Normal file
View file

@ -0,0 +1,23 @@
{
"@@locale": "es",
"appTitle": "TetraQ",
"welcomeTitle": "¡BIENVENIDO A TETRAQ!",
"nameHint": "NOMBRE",
"saveAndPlay": "GUARDAR Y JUGAR",
"onlineTitle": "ONLINE",
"onlineSub": "Desafía al mundo",
"cpuTitle": "VS CPU",
"cpuSub": "Entrena con IA",
"localTitle": "LOCAL",
"localSub": "Misma pantalla",
"leaderboardTitle": "RANKING",
"questsTitle": "MISIONES",
"themesTitle": "TEMAS",
"tutorialTitle": "TUTORIAL",
"startGame": "INICIAR JUEGO",
"createMatch": "CREAR PARTIDA",
"joinMatch": "UNIRSE",
"gameOver": "FIN DEL JUEGO",
"mainMenu": "VOLVER AL MENÚ",
"exit": "SALIR"
}

23
lib/l10n/app_fr.arb Normal file
View file

@ -0,0 +1,23 @@
{
"@@locale": "fr",
"appTitle": "TetraQ",
"welcomeTitle": "BIENVENUE DANS TETRAQ !",
"nameHint": "NOM",
"saveAndPlay": "SAUVEGARDER ET JOUER",
"onlineTitle": "EN LIGNE",
"onlineSub": "Défiez le monde",
"cpuTitle": "VS CPU",
"cpuSub": "Entraînez avec l'IA",
"localTitle": "LOCAL",
"localSub": "Même écran",
"leaderboardTitle": "CLASSEMENT",
"questsTitle": "QUÊTES",
"themesTitle": "THÈMES",
"tutorialTitle": "TUTORIEL",
"startGame": "JOUER",
"createMatch": "CRÉER UN MATCH",
"joinMatch": "REJOINDRE",
"gameOver": "FIN DE PARTIE",
"mainMenu": "RETOUR AU MENU",
"exit": "QUITTER"
}

View file

@ -1,4 +1,23 @@
{
"@@locale": "it",
"appTitle": "TetraQ",
"playLocal": "PASS & PLAY (Locale)"
}
"welcomeTitle": "BENVENUTO IN TETRAQ!",
"nameHint": "NOME",
"saveAndPlay": "SALVA E GIOCA",
"onlineTitle": "ONLINE",
"onlineSub": "Sfida il mondo",
"cpuTitle": "VS CPU",
"cpuSub": "Allenati con l'IA",
"localTitle": "LOCALE",
"localSub": "Stesso schermo",
"leaderboardTitle": "CLASSIFICA",
"questsTitle": "SFIDE",
"themesTitle": "TEMI",
"tutorialTitle": "TUTORIAL",
"startGame": "AVVIA PARTITA",
"createMatch": "CREA PARTITA",
"joinMatch": "UNISCITI",
"gameOver": "FINE PARTITA",
"mainMenu": "TORNA AL MENU",
"exit": "ESCI"
}

View file

@ -0,0 +1,286 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/intl.dart' as intl;
import 'app_localizations_de.dart';
import 'app_localizations_en.dart';
import 'app_localizations_es.dart';
import 'app_localizations_fr.dart';
import 'app_localizations_it.dart';
import 'app_localizations_pt.dart';
import 'app_localizations_ru.dart';
import 'app_localizations_zh.dart';
// ignore_for_file: type=lint
/// Callers can lookup localized strings with an instance of AppLocalizations
/// returned by `AppLocalizations.of(context)`.
///
/// Applications need to include `AppLocalizations.delegate()` in their app's
/// `localizationDelegates` list, and the locales they support in the app's
/// `supportedLocales` list. For example:
///
/// ```dart
/// import 'l10n/app_localizations.dart';
///
/// return MaterialApp(
/// localizationsDelegates: AppLocalizations.localizationsDelegates,
/// supportedLocales: AppLocalizations.supportedLocales,
/// home: MyApplicationHome(),
/// );
/// ```
///
/// ## Update pubspec.yaml
///
/// Please make sure to update your pubspec.yaml to include the following
/// packages:
///
/// ```yaml
/// dependencies:
/// # Internationalization support.
/// flutter_localizations:
/// sdk: flutter
/// intl: any # Use the pinned version from flutter_localizations
///
/// # Rest of dependencies
/// ```
///
/// ## iOS Applications
///
/// iOS applications define key application metadata, including supported
/// locales, in an Info.plist file that is built into the application bundle.
/// To configure the locales supported by your app, youll need to edit this
/// file.
///
/// First, open your projects ios/Runner.xcworkspace Xcode workspace file.
/// Then, in the Project Navigator, open the Info.plist file under the Runner
/// projects Runner folder.
///
/// Next, select the Information Property List item, select Add Item from the
/// Editor menu, then select Localizations from the pop-up menu.
///
/// Select and expand the newly-created Localizations item then, for each
/// locale your application supports, add a new item and select the locale
/// you wish to add from the pop-up menu in the Value field. This list should
/// be consistent with the languages listed in the AppLocalizations.supportedLocales
/// property.
abstract class AppLocalizations {
AppLocalizations(String locale)
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
final String localeName;
static AppLocalizations? of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
/// A list of this localizations delegate along with the default localizations
/// delegates.
///
/// Returns a list of localizations delegates containing this delegate along with
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
/// and GlobalWidgetsLocalizations.delegate.
///
/// Additional delegates can be added by appending to this list in
/// MaterialApp. This list does not have to be used at all if a custom list
/// of delegates is preferred or required.
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
<LocalizationsDelegate<dynamic>>[
delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
];
/// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[
Locale('de'),
Locale('en'),
Locale('es'),
Locale('fr'),
Locale('it'),
Locale('pt'),
Locale('ru'),
Locale('zh'),
];
/// No description provided for @appTitle.
///
/// In it, this message translates to:
/// **'TetraQ'**
String get appTitle;
/// No description provided for @welcomeTitle.
///
/// In it, this message translates to:
/// **'BENVENUTO IN TETRAQ!'**
String get welcomeTitle;
/// No description provided for @nameHint.
///
/// In it, this message translates to:
/// **'NOME'**
String get nameHint;
/// No description provided for @saveAndPlay.
///
/// In it, this message translates to:
/// **'SALVA E GIOCA'**
String get saveAndPlay;
/// No description provided for @onlineTitle.
///
/// In it, this message translates to:
/// **'ONLINE'**
String get onlineTitle;
/// No description provided for @onlineSub.
///
/// In it, this message translates to:
/// **'Sfida il mondo'**
String get onlineSub;
/// No description provided for @cpuTitle.
///
/// In it, this message translates to:
/// **'VS CPU'**
String get cpuTitle;
/// No description provided for @cpuSub.
///
/// In it, this message translates to:
/// **'Allenati con l\'IA'**
String get cpuSub;
/// No description provided for @localTitle.
///
/// In it, this message translates to:
/// **'LOCALE'**
String get localTitle;
/// No description provided for @localSub.
///
/// In it, this message translates to:
/// **'Stesso schermo'**
String get localSub;
/// No description provided for @leaderboardTitle.
///
/// In it, this message translates to:
/// **'CLASSIFICA'**
String get leaderboardTitle;
/// No description provided for @questsTitle.
///
/// In it, this message translates to:
/// **'SFIDE'**
String get questsTitle;
/// No description provided for @themesTitle.
///
/// In it, this message translates to:
/// **'TEMI'**
String get themesTitle;
/// No description provided for @tutorialTitle.
///
/// In it, this message translates to:
/// **'TUTORIAL'**
String get tutorialTitle;
/// No description provided for @startGame.
///
/// In it, this message translates to:
/// **'AVVIA PARTITA'**
String get startGame;
/// No description provided for @createMatch.
///
/// In it, this message translates to:
/// **'CREA PARTITA'**
String get createMatch;
/// No description provided for @joinMatch.
///
/// In it, this message translates to:
/// **'UNISCITI'**
String get joinMatch;
/// No description provided for @gameOver.
///
/// In it, this message translates to:
/// **'FINE PARTITA'**
String get gameOver;
/// No description provided for @mainMenu.
///
/// In it, this message translates to:
/// **'TORNA AL MENU'**
String get mainMenu;
/// No description provided for @exit.
///
/// In it, this message translates to:
/// **'ESCI'**
String get exit;
}
class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
@override
Future<AppLocalizations> load(Locale locale) {
return SynchronousFuture<AppLocalizations>(lookupAppLocalizations(locale));
}
@override
bool isSupported(Locale locale) => <String>[
'de',
'en',
'es',
'fr',
'it',
'pt',
'ru',
'zh',
].contains(locale.languageCode);
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
AppLocalizations lookupAppLocalizations(Locale locale) {
// Lookup logic when only language code is specified.
switch (locale.languageCode) {
case 'de':
return AppLocalizationsDe();
case 'en':
return AppLocalizationsEn();
case 'es':
return AppLocalizationsEs();
case 'fr':
return AppLocalizationsFr();
case 'it':
return AppLocalizationsIt();
case 'pt':
return AppLocalizationsPt();
case 'ru':
return AppLocalizationsRu();
case 'zh':
return AppLocalizationsZh();
}
throw FlutterError(
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
'an issue with the localizations generation tool. Please file an issue '
'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.',
);
}

View file

@ -0,0 +1,70 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for German (`de`).
class AppLocalizationsDe extends AppLocalizations {
AppLocalizationsDe([String locale = 'de']) : super(locale);
@override
String get appTitle => 'TetraQ';
@override
String get welcomeTitle => 'WILLKOMMEN BEI TETRAQ!';
@override
String get nameHint => 'NAME';
@override
String get saveAndPlay => 'SPEICHERN & SPIELEN';
@override
String get onlineTitle => 'ONLINE';
@override
String get onlineSub => 'Fordere die Welt heraus';
@override
String get cpuTitle => 'VS CPU';
@override
String get cpuSub => 'Trainiere mit KI';
@override
String get localTitle => 'LOKAL';
@override
String get localSub => 'Gleicher Bildschirm';
@override
String get leaderboardTitle => 'RANGLISTE';
@override
String get questsTitle => 'MISSIONEN';
@override
String get themesTitle => 'THEMEN';
@override
String get tutorialTitle => 'TUTORIAL';
@override
String get startGame => 'SPIEL STARTEN';
@override
String get createMatch => 'SPIEL ERSTELLEN';
@override
String get joinMatch => 'BEITRETEN';
@override
String get gameOver => 'SPIELENDE';
@override
String get mainMenu => 'ZURÜCK ZUM MENÜ';
@override
String get exit => 'BEENDEN';
}

View file

@ -0,0 +1,70 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for English (`en`).
class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale);
@override
String get appTitle => 'TetraQ';
@override
String get welcomeTitle => 'WELCOME TO TETRAQ!';
@override
String get nameHint => 'NAME';
@override
String get saveAndPlay => 'SAVE & PLAY';
@override
String get onlineTitle => 'ONLINE';
@override
String get onlineSub => 'Challenge the world';
@override
String get cpuTitle => 'VS CPU';
@override
String get cpuSub => 'Train with AI';
@override
String get localTitle => 'LOCAL';
@override
String get localSub => 'Same screen';
@override
String get leaderboardTitle => 'LEADERBOARD';
@override
String get questsTitle => 'QUESTS';
@override
String get themesTitle => 'THEMES';
@override
String get tutorialTitle => 'TUTORIAL';
@override
String get startGame => 'START GAME';
@override
String get createMatch => 'CREATE MATCH';
@override
String get joinMatch => 'JOIN';
@override
String get gameOver => 'GAME OVER';
@override
String get mainMenu => 'BACK TO MENU';
@override
String get exit => 'EXIT';
}

View file

@ -0,0 +1,70 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for Spanish Castilian (`es`).
class AppLocalizationsEs extends AppLocalizations {
AppLocalizationsEs([String locale = 'es']) : super(locale);
@override
String get appTitle => 'TetraQ';
@override
String get welcomeTitle => '¡BIENVENIDO A TETRAQ!';
@override
String get nameHint => 'NOMBRE';
@override
String get saveAndPlay => 'GUARDAR Y JUGAR';
@override
String get onlineTitle => 'ONLINE';
@override
String get onlineSub => 'Desafía al mundo';
@override
String get cpuTitle => 'VS CPU';
@override
String get cpuSub => 'Entrena con IA';
@override
String get localTitle => 'LOCAL';
@override
String get localSub => 'Misma pantalla';
@override
String get leaderboardTitle => 'RANKING';
@override
String get questsTitle => 'MISIONES';
@override
String get themesTitle => 'TEMAS';
@override
String get tutorialTitle => 'TUTORIAL';
@override
String get startGame => 'INICIAR JUEGO';
@override
String get createMatch => 'CREAR PARTIDA';
@override
String get joinMatch => 'UNIRSE';
@override
String get gameOver => 'FIN DEL JUEGO';
@override
String get mainMenu => 'VOLVER AL MENÚ';
@override
String get exit => 'SALIR';
}

View file

@ -0,0 +1,70 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for French (`fr`).
class AppLocalizationsFr extends AppLocalizations {
AppLocalizationsFr([String locale = 'fr']) : super(locale);
@override
String get appTitle => 'TetraQ';
@override
String get welcomeTitle => 'BIENVENUE DANS TETRAQ !';
@override
String get nameHint => 'NOM';
@override
String get saveAndPlay => 'SAUVEGARDER ET JOUER';
@override
String get onlineTitle => 'EN LIGNE';
@override
String get onlineSub => 'Défiez le monde';
@override
String get cpuTitle => 'VS CPU';
@override
String get cpuSub => 'Entraînez avec l\'IA';
@override
String get localTitle => 'LOCAL';
@override
String get localSub => 'Même écran';
@override
String get leaderboardTitle => 'CLASSEMENT';
@override
String get questsTitle => 'QUÊTES';
@override
String get themesTitle => 'THÈMES';
@override
String get tutorialTitle => 'TUTORIEL';
@override
String get startGame => 'JOUER';
@override
String get createMatch => 'CRÉER UN MATCH';
@override
String get joinMatch => 'REJOINDRE';
@override
String get gameOver => 'FIN DE PARTIE';
@override
String get mainMenu => 'RETOUR AU MENU';
@override
String get exit => 'QUITTER';
}

View file

@ -0,0 +1,70 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for Italian (`it`).
class AppLocalizationsIt extends AppLocalizations {
AppLocalizationsIt([String locale = 'it']) : super(locale);
@override
String get appTitle => 'TetraQ';
@override
String get welcomeTitle => 'BENVENUTO IN TETRAQ!';
@override
String get nameHint => 'NOME';
@override
String get saveAndPlay => 'SALVA E GIOCA';
@override
String get onlineTitle => 'ONLINE';
@override
String get onlineSub => 'Sfida il mondo';
@override
String get cpuTitle => 'VS CPU';
@override
String get cpuSub => 'Allenati con l\'IA';
@override
String get localTitle => 'LOCALE';
@override
String get localSub => 'Stesso schermo';
@override
String get leaderboardTitle => 'CLASSIFICA';
@override
String get questsTitle => 'SFIDE';
@override
String get themesTitle => 'TEMI';
@override
String get tutorialTitle => 'TUTORIAL';
@override
String get startGame => 'AVVIA PARTITA';
@override
String get createMatch => 'CREA PARTITA';
@override
String get joinMatch => 'UNISCITI';
@override
String get gameOver => 'FINE PARTITA';
@override
String get mainMenu => 'TORNA AL MENU';
@override
String get exit => 'ESCI';
}

View file

@ -0,0 +1,70 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for Portuguese (`pt`).
class AppLocalizationsPt extends AppLocalizations {
AppLocalizationsPt([String locale = 'pt']) : super(locale);
@override
String get appTitle => 'TetraQ';
@override
String get welcomeTitle => 'BEM-VINDO AO TETRAQ!';
@override
String get nameHint => 'NOME';
@override
String get saveAndPlay => 'SALVAR E JOGAR';
@override
String get onlineTitle => 'ONLINE';
@override
String get onlineSub => 'Desafie o mundo';
@override
String get cpuTitle => 'VS CPU';
@override
String get cpuSub => 'Treine com a IA';
@override
String get localTitle => 'LOCAL';
@override
String get localSub => 'Mesma tela';
@override
String get leaderboardTitle => 'CLASSIFICAÇÃO';
@override
String get questsTitle => 'DESAFIOS';
@override
String get themesTitle => 'TEMAS';
@override
String get tutorialTitle => 'TUTORIAL';
@override
String get startGame => 'INICIAR JOGO';
@override
String get createMatch => 'CRIAR PARTIDA';
@override
String get joinMatch => 'ENTRAR';
@override
String get gameOver => 'FIM DE JOGO';
@override
String get mainMenu => 'VOLTAR AO MENU';
@override
String get exit => 'SAIR';
}

View file

@ -0,0 +1,70 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for Russian (`ru`).
class AppLocalizationsRu extends AppLocalizations {
AppLocalizationsRu([String locale = 'ru']) : super(locale);
@override
String get appTitle => 'TetraQ';
@override
String get welcomeTitle => 'ДОБРО ПОЖАЛОВАТЬ В TETRAQ!';
@override
String get nameHint => 'ИМЯ';
@override
String get saveAndPlay => 'СОХРАНИТЬ И ИГРАТЬ';
@override
String get onlineTitle => 'ОНЛАЙН';
@override
String get onlineSub => 'Брось вызов миру';
@override
String get cpuTitle => 'VS ИИ';
@override
String get cpuSub => 'Тренировка с ИИ';
@override
String get localTitle => 'ЛОКАЛЬНО';
@override
String get localSub => 'Один экран';
@override
String get leaderboardTitle => 'РЕЙТИНГ';
@override
String get questsTitle => 'ЗАДАНИЯ';
@override
String get themesTitle => 'ТЕМЫ';
@override
String get tutorialTitle => 'ОБУЧЕНИЕ';
@override
String get startGame => 'НАЧАТЬ ИГРУ';
@override
String get createMatch => 'СОЗДАТЬ ИГРУ';
@override
String get joinMatch => 'ПРИСОЕДИНИТЬСЯ';
@override
String get gameOver => 'ИГРА ОКОНЧЕНА';
@override
String get mainMenu => 'В ГЛАВНОЕ МЕНЮ';
@override
String get exit => 'ВЫХОД';
}

View file

@ -0,0 +1,70 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for Chinese (`zh`).
class AppLocalizationsZh extends AppLocalizations {
AppLocalizationsZh([String locale = 'zh']) : super(locale);
@override
String get appTitle => 'TetraQ';
@override
String get welcomeTitle => '欢迎来到 TETRAQ';
@override
String get nameHint => '名字';
@override
String get saveAndPlay => '保存并开始';
@override
String get onlineTitle => '在线匹配';
@override
String get onlineSub => '挑战世界';
@override
String get cpuTitle => '人机对战';
@override
String get cpuSub => '与AI训练';
@override
String get localTitle => '本地游戏';
@override
String get localSub => '同屏对战';
@override
String get leaderboardTitle => '排行榜';
@override
String get questsTitle => '任务';
@override
String get themesTitle => '主题';
@override
String get tutorialTitle => '教程';
@override
String get startGame => '开始游戏';
@override
String get createMatch => '创建比赛';
@override
String get joinMatch => '加入';
@override
String get gameOver => '游戏结束';
@override
String get mainMenu => '返回主菜单';
@override
String get exit => '退出';
}

23
lib/l10n/app_pt.arb Normal file
View file

@ -0,0 +1,23 @@
{
"@@locale": "pt",
"appTitle": "TetraQ",
"welcomeTitle": "BEM-VINDO AO TETRAQ!",
"nameHint": "NOME",
"saveAndPlay": "SALVAR E JOGAR",
"onlineTitle": "ONLINE",
"onlineSub": "Desafie o mundo",
"cpuTitle": "VS CPU",
"cpuSub": "Treine com a IA",
"localTitle": "LOCAL",
"localSub": "Mesma tela",
"leaderboardTitle": "CLASSIFICAÇÃO",
"questsTitle": "DESAFIOS",
"themesTitle": "TEMAS",
"tutorialTitle": "TUTORIAL",
"startGame": "INICIAR JOGO",
"createMatch": "CRIAR PARTIDA",
"joinMatch": "ENTRAR",
"gameOver": "FIM DE JOGO",
"mainMenu": "VOLTAR AO MENU",
"exit": "SAIR"
}

23
lib/l10n/app_ru.arb Normal file
View file

@ -0,0 +1,23 @@
{
"@@locale": "ru",
"appTitle": "TetraQ",
"welcomeTitle": "ДОБРО ПОЖАЛОВАТЬ В TETRAQ!",
"nameHint": "ИМЯ",
"saveAndPlay": "СОХРАНИТЬ И ИГРАТЬ",
"onlineTitle": "ОНЛАЙН",
"onlineSub": "Брось вызов миру",
"cpuTitle": "VS ИИ",
"cpuSub": "Тренировка с ИИ",
"localTitle": "ЛОКАЛЬНО",
"localSub": "Один экран",
"leaderboardTitle": "РЕЙТИНГ",
"questsTitle": "ЗАДАНИЯ",
"themesTitle": "ТЕМЫ",
"tutorialTitle": "ОБУЧЕНИЕ",
"startGame": "НАЧАТЬ ИГРУ",
"createMatch": "СОЗДАТЬ ИГРУ",
"joinMatch": "ПРИСОЕДИНИТЬСЯ",
"gameOver": "ИГРА ОКОНЧЕНА",
"mainMenu": "В ГЛАВНОЕ МЕНЮ",
"exit": "ВЫХОД"
}

23
lib/l10n/app_zh.arb Normal file
View file

@ -0,0 +1,23 @@
{
"@@locale": "zh",
"appTitle": "TetraQ",
"welcomeTitle": "欢迎来到 TETRAQ",
"nameHint": "名字",
"saveAndPlay": "保存并开始",
"onlineTitle": "在线匹配",
"onlineSub": "挑战世界",
"cpuTitle": "人机对战",
"cpuSub": "与AI训练",
"localTitle": "本地游戏",
"localSub": "同屏对战",
"leaderboardTitle": "排行榜",
"questsTitle": "任务",
"themesTitle": "主题",
"tutorialTitle": "教程",
"startGame": "开始游戏",
"createMatch": "创建比赛",
"joinMatch": "加入",
"gameOver": "游戏结束",
"mainMenu": "返回主菜单",
"exit": "退出"
}

View file

@ -3,45 +3,41 @@
// ===========================================================================
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart'; // <-- AGGIUNTO PER kDebugMode
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
import 'core/theme_manager.dart';
import 'logic/game_controller.dart';
import 'ui/home/home_screen.dart';
import 'services/storage_service.dart';
import 'services/audio_service.dart'; // <-- NUOVO IMPORT PER L'AUDIO
import 'services/audio_service.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'firebase_options.dart';
import 'package:firebase_app_check/firebase_app_check.dart'; // <-- IMPORT APP CHECK
import 'package:firebase_app_check/firebase_app_check.dart';
// --- IMPORT PER IL SUPPORTO MULTILINGUA ---
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:tetraq/l10n/app_localizations.dart';
void main() async {
// Assicuriamoci che i motori di Flutter siano pronti
WidgetsFlutterBinding.ensureInitialized();
// 1. Accendiamo Firebase!
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// --- NUOVO: SCUDO APP CHECK ---
await FirebaseAppCheck.instance.activate(
// Se stai programmando (Debug), usa una chiave finta. Se l'app è sugli Store, usa i veri sistemi di sicurezza Apple/Google.
androidProvider: kDebugMode ? AndroidProvider.debug : AndroidProvider.playIntegrity,
appleProvider: kDebugMode ? AppleProvider.debug : AppleProvider.deviceCheck,
);
// 2. Login Silenzioso (Crea la nostra "Identità Sicura" per Firebase)
try {
await FirebaseAuth.instance.signInAnonymously();
} catch (e) {
debugPrint("Errore Auth: $e");
}
// 3. Accendiamo la Memoria Locale!
await StorageService.instance.init();
// 4. Accendiamo la Radio! (Lettore Musicale)
await AudioService.instance.init();
runApp(
@ -67,6 +63,14 @@ class TetraQApp extends StatelessWidget {
fontFamily: 'Roboto',
useMaterial3: true,
),
// --- BIVIO DELLE LINGUE ATTIVATO! ---
// Flutter si occuperà di caricare automaticamente tutte le lingue
// che hai generato tramite lo script.
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
// ------------------------------------
home: const HomeScreen(),
);
}

View file

@ -21,6 +21,7 @@ import '../../services/storage_service.dart';
import '../multiplayer/lobby_screen.dart';
import 'history_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:tetraq/l10n/app_localizations.dart';
TextStyle _getTextStyle(AppThemeType themeType, TextStyle baseStyle) {
if (themeType == AppThemeType.doodle) {
@ -429,6 +430,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
final theme = themeManager.currentColors;
final themeType = themeManager.currentThemeType;
Color inkColor = const Color(0xFF111122);
final loc = AppLocalizations.of(context)!;
Widget dialogContent = themeType == AppThemeType.doodle
? CustomPaint(
@ -438,7 +440,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('BENVENUTO!', style: _getTextStyle(themeType, TextStyle(color: inkColor, fontWeight: FontWeight.w900, fontSize: 28, letterSpacing: 2.0)), textAlign: TextAlign.center),
Text(loc.welcomeTitle, style: _getTextStyle(themeType, TextStyle(color: inkColor, fontWeight: FontWeight.w900, fontSize: 28, letterSpacing: 2.0)), textAlign: TextAlign.center),
const SizedBox(height: 20),
Text('Scegli il tuo nome da battaglia', style: _getTextStyle(themeType, TextStyle(color: inkColor.withOpacity(0.8), fontSize: 18)), textAlign: TextAlign.center),
const SizedBox(height: 30),
@ -446,7 +448,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
controller: nameController, textCapitalization: TextCapitalization.characters, textAlign: TextAlign.center, maxLength: 5,
style: _getTextStyle(themeType, TextStyle(color: inkColor, fontSize: 36, fontWeight: FontWeight.bold, letterSpacing: 8)),
decoration: InputDecoration(
hintText: 'NOME', hintStyle: _getTextStyle(themeType, TextStyle(color: inkColor.withOpacity(0.3), letterSpacing: 4)),
hintText: loc.nameHint, hintStyle: _getTextStyle(themeType, TextStyle(color: inkColor.withOpacity(0.3), letterSpacing: 4)),
filled: false, counterText: "",
enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: inkColor, width: 3)),
focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Colors.red.shade200, width: 5)),
@ -467,7 +469,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
child: Container(
width: double.infinity, height: 60,
alignment: Alignment.center,
child: Text('SALVA E GIOCA', style: _getTextStyle(themeType, TextStyle(color: inkColor, fontSize: 22, fontWeight: FontWeight.bold, letterSpacing: 1.5))),
child: Text(loc.saveAndPlay, style: _getTextStyle(themeType, TextStyle(color: inkColor, fontSize: 22, fontWeight: FontWeight.bold, letterSpacing: 1.5))),
),
),
),
@ -488,7 +490,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('BENVENUTO IN TETRAQ!', style: _getTextStyle(themeType, TextStyle(color: theme.text, fontWeight: FontWeight.w900, fontSize: 24, letterSpacing: 1.5)), textAlign: TextAlign.center),
Text(loc.welcomeTitle, style: _getTextStyle(themeType, TextStyle(color: theme.text, fontWeight: FontWeight.w900, fontSize: 24, letterSpacing: 1.5)), textAlign: TextAlign.center),
const SizedBox(height: 20),
Text('Scegli il tuo nome da battaglia per sfidare i tuoi amici online.', style: _getTextStyle(themeType, TextStyle(color: theme.text.withOpacity(0.8), fontSize: 16)), textAlign: TextAlign.center),
const SizedBox(height: 40),
@ -496,7 +498,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
controller: nameController, textCapitalization: TextCapitalization.characters, textAlign: TextAlign.center, maxLength: 5,
style: _getTextStyle(themeType, TextStyle(color: theme.text, fontSize: 32, fontWeight: FontWeight.bold, letterSpacing: 8)),
decoration: InputDecoration(
hintText: 'NOME', hintStyle: _getTextStyle(themeType, TextStyle(color: theme.text.withOpacity(0.3), letterSpacing: 4)),
hintText: loc.nameHint, hintStyle: _getTextStyle(themeType, TextStyle(color: theme.text.withOpacity(0.3), letterSpacing: 4)),
filled: true, fillColor: theme.text.withOpacity(0.05), counterText: "",
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: theme.gridLine.withOpacity(0.5), width: 2), borderRadius: BorderRadius.circular(15)),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: theme.playerBlue, width: 3), borderRadius: BorderRadius.circular(15)),
@ -515,7 +517,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
setState(() {});
}
},
child: Text('SALVA E GIOCA', style: _getTextStyle(themeType, const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, letterSpacing: 1.5))),
child: Text(loc.saveAndPlay, style: _getTextStyle(themeType, const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, letterSpacing: 1.5))),
),
),
],
@ -575,7 +577,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
Navigator.of(context).pop();
Navigator.push(context, MaterialPageRoute(builder: (_) => LobbyScreen(initialRoomCode: roomCode)));
},
child: Text("Unisciti", style: _getTextStyle(themeType, TextStyle(color: themeType == AppThemeType.doodle ? theme.text : Colors.white, fontWeight: FontWeight.bold))),
child: Text(AppLocalizations.of(context)!.joinMatch, style: _getTextStyle(themeType, TextStyle(color: themeType == AppThemeType.doodle ? theme.text : Colors.white, fontWeight: FontWeight.bold))),
),
],
);
@ -588,6 +590,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
ArenaShape localShape = ArenaShape.classic;
bool localTimeMode = true;
bool isChaosUnlocked = StorageService.instance.playerLevel >= 10;
final loc = AppLocalizations.of(context)!;
showDialog(
context: context,
@ -612,7 +615,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(isVsCPU ? "SFIDA IA" : "MODALITÀ LOCALE", style: _getTextStyle(themeType, TextStyle(fontSize: 26, fontWeight: FontWeight.w900, color: inkColor, letterSpacing: 2))),
Text(isVsCPU ? loc.cpuTitle : loc.localTitle, style: _getTextStyle(themeType, TextStyle(fontSize: 26, fontWeight: FontWeight.w900, color: inkColor, letterSpacing: 2))),
const SizedBox(height: 25),
Text("FORMA ARENA", style: _getTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.w900, color: inkColor.withOpacity(0.6), letterSpacing: 1.5))),
@ -667,7 +670,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
child: Container(
height: 65, width: double.infinity,
alignment: Alignment.center,
child: Text("AVVIA PARTITA", style: _getTextStyle(themeType, TextStyle(fontSize: 22, fontWeight: FontWeight.w900, letterSpacing: 3.0, color: inkColor))),
child: Text(loc.startGame, style: _getTextStyle(themeType, TextStyle(fontSize: 22, fontWeight: FontWeight.w900, letterSpacing: 3.0, color: inkColor))),
),
),
),
@ -692,7 +695,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(isVsCPU ? "SFIDA IA" : "MODALITÀ LOCALE", style: _getTextStyle(themeType, TextStyle(fontSize: 24, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 2))),
Text(isVsCPU ? loc.cpuTitle : loc.localTitle, style: _getTextStyle(themeType, TextStyle(fontSize: 24, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 2))),
const SizedBox(height: 20),
Text("FORMA ARENA", style: _getTextStyle(themeType, TextStyle(fontSize: 12, fontWeight: FontWeight.w900, color: theme.text.withOpacity(0.5), letterSpacing: 1.5))),
@ -743,7 +746,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
context.read<GameController>().startNewGame(localRadius, vsCPU: isVsCPU, shape: localShape, timeMode: localTimeMode);
Navigator.push(context, MaterialPageRoute(builder: (_) => const GameScreen()));
},
child: const Text("AVVIA PARTITA", style: TextStyle(fontSize: 18, fontWeight: FontWeight.w900, letterSpacing: 2)),
child: Text(loc.startGame, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w900, letterSpacing: 2)),
),
)
],
@ -775,6 +778,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
final theme = themeManager.currentColors;
final themeType = themeManager.currentThemeType;
Color inkColor = const Color(0xFF111122);
final loc = AppLocalizations.of(context)!;
return Dialog(
backgroundColor: Colors.transparent,
@ -792,7 +796,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
children: [
Icon(Icons.assignment_turned_in, size: 50, color: theme.playerBlue),
const SizedBox(height: 10),
Text("SFIDE GIORNALIERE", style: _getTextStyle(themeType, TextStyle(fontSize: 22, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 1.5))),
Text(loc.questsTitle, style: _getTextStyle(themeType, TextStyle(fontSize: 22, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 1.5))),
const SizedBox(height: 25),
// Generiamo dinamicamente le 3 missioni salvate in memoria
@ -874,6 +878,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
final themeManager = ctx.watch<ThemeManager>();
final theme = themeManager.currentColors;
final themeType = themeManager.currentThemeType;
final loc = AppLocalizations.of(context)!;
Widget content = Container(
padding: const EdgeInsets.all(20.0),
@ -888,7 +893,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
children: [
Icon(Icons.emoji_events, size: 50, color: Colors.amber),
const SizedBox(height: 10),
Text("CLASSIFICA MONDIALE", style: _getTextStyle(themeType, TextStyle(fontSize: 20, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 1.5))),
Text(loc.leaderboardTitle, style: _getTextStyle(themeType, TextStyle(fontSize: 20, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 1.5))),
const SizedBox(height: 20),
// Lista giocatori pescata da Firebase!
@ -971,6 +976,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
final theme = themeManager.currentColors;
final themeType = themeManager.currentThemeType;
Color inkColor = const Color(0xFF111122);
final loc = AppLocalizations.of(context)!;
String goldLabel = themeType == AppThemeType.grimorio ? "CORONA:" : "ORO:";
String bombLabel = themeType == AppThemeType.grimorio ? "STREGA:" : "BOMBA:";
@ -1106,6 +1112,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
final themeType = themeManager.currentThemeType;
final theme = themeManager.currentColors;
Color inkColor = const Color(0xFF111122);
final loc = AppLocalizations.of(context)!;
String? bgImage;
if (themeType == AppThemeType.wood) bgImage = 'assets/images/wood_bg.jpg';
@ -1245,7 +1252,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
"TETRAQ",
loc.appTitle.toUpperCase(),
style: _getTextStyle(themeType, TextStyle(
fontSize: 65,
fontWeight: FontWeight.w900,
@ -1268,19 +1275,19 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildCyberCard(_FeatureCard(title: "ONLINE", subtitle: "Sfida il mondo", icon: Icons.public, color: Colors.lightBlue.shade200, theme: theme, themeType: themeType, isFeatured: true, onTap: () { Navigator.push(context, MaterialPageRoute(builder: (_) => const LobbyScreen())); }), themeType),
_buildCyberCard(_FeatureCard(title: loc.onlineTitle, subtitle: loc.onlineSub, icon: Icons.public, color: Colors.lightBlue.shade200, theme: theme, themeType: themeType, isFeatured: true, onTap: () { Navigator.push(context, MaterialPageRoute(builder: (_) => const LobbyScreen())); }), themeType),
const SizedBox(height: 12),
_buildCyberCard(_FeatureCard(title: "VS CPU", subtitle: "Allenati con l'IA", icon: Icons.smart_toy, color: Colors.purple.shade200, theme: theme, themeType: themeType, onTap: () => _showMatchSetupDialog(true)), themeType),
_buildCyberCard(_FeatureCard(title: loc.cpuTitle, subtitle: loc.cpuSub, icon: Icons.smart_toy, color: Colors.purple.shade200, theme: theme, themeType: themeType, onTap: () => _showMatchSetupDialog(true)), themeType),
const SizedBox(height: 12),
_buildCyberCard(_FeatureCard(title: "LOCALE", subtitle: "Stesso schermo", icon: Icons.people_alt, color: Colors.red.shade200, theme: theme, themeType: themeType, onTap: () => _showMatchSetupDialog(false)), themeType),
_buildCyberCard(_FeatureCard(title: loc.localTitle, subtitle: loc.localSub, icon: Icons.people_alt, color: Colors.red.shade200, theme: theme, themeType: themeType, onTap: () => _showMatchSetupDialog(false)), themeType),
const SizedBox(height: 12),
// NUOVI BOTTONI PER LA VERSIONE 2.0
Row(
children: [
Expanded(child: _buildCyberCard(_FeatureCard(title: "CLASSIFICA", subtitle: "Top 50 Globale", icon: Icons.leaderboard, color: Colors.amber.shade200, theme: theme, themeType: themeType, onTap: _showLeaderboardDialog, compact: true), themeType)),
Expanded(child: _buildCyberCard(_FeatureCard(title: loc.leaderboardTitle, subtitle: "Top 50 Globale", icon: Icons.leaderboard, color: Colors.amber.shade200, theme: theme, themeType: themeType, onTap: _showLeaderboardDialog, compact: true), themeType)),
const SizedBox(width: 12),
Expanded(child: _buildCyberCard(_FeatureCard(title: "SFIDE", subtitle: "Missioni", icon: Icons.assignment_turned_in, color: Colors.green.shade200, theme: theme, themeType: themeType, onTap: _showDailyQuestsDialog, compact: true), themeType)),
Expanded(child: _buildCyberCard(_FeatureCard(title: loc.questsTitle, subtitle: "Missioni", icon: Icons.assignment_turned_in, color: Colors.green.shade200, theme: theme, themeType: themeType, onTap: _showDailyQuestsDialog, compact: true), themeType)),
],
),
@ -1288,9 +1295,9 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
Row(
children: [
Expanded(child: _buildCyberCard(_FeatureCard(title: "TEMI", subtitle: "Personalizza", icon: Icons.palette, color: Colors.teal.shade200, theme: theme, themeType: themeType, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const SettingsScreen())), compact: true), themeType)),
Expanded(child: _buildCyberCard(_FeatureCard(title: loc.themesTitle, subtitle: "Personalizza", icon: Icons.palette, color: Colors.teal.shade200, theme: theme, themeType: themeType, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const SettingsScreen())), compact: true), themeType)),
const SizedBox(width: 12),
Expanded(child: _buildCyberCard(_FeatureCard(title: "TUTORIAL", subtitle: "Come giocare", icon: Icons.school, color: Colors.indigo.shade200, theme: theme, themeType: themeType, onTap: _showTutorialDialog, compact: true), themeType)),
Expanded(child: _buildCyberCard(_FeatureCard(title: loc.tutorialTitle, subtitle: "Come giocare", icon: Icons.school, color: Colors.indigo.shade200, theme: theme, themeType: themeType, onTap: _showTutorialDialog, compact: true), themeType)),
],
),
],

View file

@ -129,6 +129,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.2"
change_app_package_name:
dependency: "direct dev"
description:
name: change_app_package_name
sha256: "8e43b754fe960426904d77ed4c62fa8c9834deaf6e293ae40963fa447482c4c5"
url: "https://pub.dev"
source: hosted
version: "1.5.0"
characters:
dependency: transitive
description:

View file

@ -1,7 +1,7 @@
name: tetraq
description: A new Flutter project.
publish_to: 'none'
version: 1.0.2+4
version: 1.1.3+5
environment:
sdk: ^3.10.7
@ -31,6 +31,7 @@ dev_dependencies:
sdk: flutter
flutter_lints: ^6.0.0
flutter_launcher_icons: ^0.13.1
change_app_package_name: ^1.5.0
flutter:
uses-material-design: true