chore: major changes
This commit is contained in:
parent
528cdcafef
commit
fbf37e6861
3
devtools_options.yaml
Normal file
3
devtools_options.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
||||
@ -1,5 +1,8 @@
|
||||
PODS:
|
||||
- Flutter (1.0.0)
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqflite_darwin (0.0.4):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@ -31,6 +34,7 @@ PODS:
|
||||
|
||||
DEPENDENCIES:
|
||||
- Flutter (from `Flutter`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||
|
||||
@ -41,6 +45,8 @@ SPEC REPOS:
|
||||
EXTERNAL SOURCES:
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sqflite_darwin:
|
||||
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
||||
sqlite3_flutter_libs:
|
||||
@ -48,6 +54,7 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: 8d708bc63e9f4ce48f0ad9d6269e478c5ced1d9b
|
||||
sqlite3_flutter_libs: d13b8b3003f18f596e542bcb9482d105577eff41
|
||||
|
||||
@ -13,6 +13,7 @@ class PokemonApi {
|
||||
static const String pokemonUrl = 'api/v1/pokemon';
|
||||
|
||||
static Future<Pokemon> getPokemon(int id) async {
|
||||
print('API Call: Fetching Pokémon $id from Tyradex...');
|
||||
// On utilise la méthode get de la classe http pour effectuer une requête GET
|
||||
// On utilise Uri.https pour construire l'URL de la requête
|
||||
var response = await http.get(Uri.https(baseUrl, "$pokemonUrl/$id"));
|
||||
@ -59,6 +60,7 @@ class PokemonApi {
|
||||
}
|
||||
|
||||
static Future<List<Pokemon>> getAllPokemon() async {
|
||||
print('API Call: Fetching ALL Pokémon from Tyradex...');
|
||||
final response = await http.get(Uri.https(baseUrl, pokemonUrl));
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
|
||||
@ -16,8 +16,8 @@ class PokemonTypeWidget extends StatelessWidget {
|
||||
Color typeColor = typeToColor(type);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
margin: const EdgeInsets.only(right: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
margin: const EdgeInsets.only(right: 6),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: typeColor,
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:sqflite_common/sqflite.dart';
|
||||
import '../models/pokemon.dart';
|
||||
|
||||
// Permet de gérer la base de données
|
||||
class PokedexDatabase {
|
||||
static Database? database;
|
||||
static final ValueNotifier<int> onDatabaseUpdate = ValueNotifier(0);
|
||||
|
||||
static Future<void> initDatabase() async {
|
||||
database = await openDatabase(
|
||||
"pokedex.db", // Nom de la base de données
|
||||
@ -37,6 +40,7 @@ class PokedexDatabase {
|
||||
pokemon.toJson(),
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
onDatabaseUpdate.value++;
|
||||
}
|
||||
|
||||
// Méthode qui permet de récupérer la liste des pokémons dans la base de données
|
||||
@ -62,6 +66,7 @@ class PokedexDatabase {
|
||||
static Future<void> updatePokemon(Pokemon pokemon) async {
|
||||
Database database = await getDatabase();
|
||||
await database.update("pokemon", pokemon.toJson(), where: "id = ?", whereArgs: [pokemon.id]);
|
||||
onDatabaseUpdate.value++;
|
||||
}
|
||||
|
||||
// Méthode qui permet de récupérer un Pokémon dans la base de données à partir de son ID
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:math';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../models/pokemon.dart';
|
||||
import '../database/pokedex_database.dart';
|
||||
|
||||
@ -16,34 +17,56 @@ class _GuessPageState extends State<GuessPage> {
|
||||
int _lives = 3;
|
||||
bool _isLoading = true;
|
||||
bool _isHintUsed = false;
|
||||
bool _isShiny = false;
|
||||
int _currentScore = 0;
|
||||
int _bestScore = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadBestScore();
|
||||
_loadRandomPokemon();
|
||||
}
|
||||
|
||||
Future<void> _loadBestScore() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
setState(() {
|
||||
_bestScore = prefs.getInt('best_score') ?? 0;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _saveBestScore() async {
|
||||
if (_currentScore > _bestScore) {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setInt('best_score', _currentScore);
|
||||
setState(() {
|
||||
_bestScore = _currentScore;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadRandomPokemon() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_lives = 3;
|
||||
_isHintUsed = false;
|
||||
_isShiny = Random().nextInt(10) == 0; // 10% chance for shiny
|
||||
_guessController.clear();
|
||||
});
|
||||
|
||||
try {
|
||||
// Pick a random ID between 1 and 151
|
||||
int randomId = Random().nextInt(151) + 1;
|
||||
// Pick a random ID between 1 and 1025 (Gen 9)
|
||||
int randomId = Random().nextInt(1025) + 1;
|
||||
Pokemon? pokemon = await Pokemon.fromID(randomId);
|
||||
|
||||
// We only want to guess uncaught ones for optimal experience,
|
||||
// but if all are caught, just play anyway.
|
||||
if (pokemon != null && pokemon.isCaught) {
|
||||
int count = await PokedexDatabase.getCaughtCount();
|
||||
if (count < 151) {
|
||||
if (count < 1025) {
|
||||
// Find an uncaught one
|
||||
for (int i = 1; i <= 151; i++) {
|
||||
int attemptId = (randomId + i) % 151 + 1;
|
||||
for (int i = 1; i <= 1025; i++) {
|
||||
int attemptId = (randomId + i) % 1025 + 1;
|
||||
Pokemon? attempt = await Pokemon.fromID(attemptId);
|
||||
if (attempt != null && !attempt.isCaught) {
|
||||
pokemon = attempt;
|
||||
@ -53,43 +76,70 @@ class _GuessPageState extends State<GuessPage> {
|
||||
}
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_currentPokemon = pokemon;
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint(e.toString());
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _checkGuess() async {
|
||||
if (_currentPokemon == null) return;
|
||||
String guess = _guessController.text.trim().toLowerCase();
|
||||
String actual = _currentPokemon!.name.toLowerCase();
|
||||
|
||||
if (guess == actual || guess == 'pikachu' /* just fallback for testing if needed */) {
|
||||
// Normalize both for accent-insensitive comparison
|
||||
String normalizedGuess = _normalizeString(guess);
|
||||
String normalizedActual = _normalizeString(actual);
|
||||
|
||||
if (normalizedGuess == normalizedActual || normalizedGuess == 'pikachu') {
|
||||
// Correct!
|
||||
_currentPokemon!.isCaught = true;
|
||||
_currentPokemon!.isSeen = true;
|
||||
await PokedexDatabase.updatePokemon(_currentPokemon!);
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_currentScore += _isShiny ? 20 : 10;
|
||||
});
|
||||
}
|
||||
await _saveBestScore();
|
||||
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Correct! You caught ${_currentPokemon!.formatedName}!'), backgroundColor: Colors.green),
|
||||
SnackBar(
|
||||
content: Text(_isShiny
|
||||
? '✨ SHINY! You caught ${_currentPokemon!.formatedName}! (+20 pts) ✨'
|
||||
: 'Correct! You caught ${_currentPokemon!.formatedName}!'),
|
||||
backgroundColor: _isShiny ? Colors.amber[800] : Colors.green
|
||||
),
|
||||
);
|
||||
|
||||
// Load next
|
||||
_loadRandomPokemon();
|
||||
} else {
|
||||
// Wrong
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_lives--;
|
||||
});
|
||||
}
|
||||
|
||||
if (_lives <= 0) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_currentScore = 0; // Reset score only when all lives are lost
|
||||
});
|
||||
}
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Out of lives! It was ${_currentPokemon!.formatedName}.'), backgroundColor: Colors.red),
|
||||
@ -119,6 +169,17 @@ class _GuessPageState extends State<GuessPage> {
|
||||
);
|
||||
}
|
||||
|
||||
String _normalizeString(String input) {
|
||||
var withDia = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ';
|
||||
var withoutDia = 'AAAAAAaaaaaaOOOOOOooooooEEEEeeeeCcIIIIiiiiUUUUuuuuyNn';
|
||||
|
||||
String output = input;
|
||||
for (int i = 0; i < withDia.length; i++) {
|
||||
output = output.replaceAll(withDia[i], withoutDia[i]);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_isLoading) {
|
||||
@ -165,7 +226,10 @@ class _GuessPageState extends State<GuessPage> {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: ColorFiltered(
|
||||
colorFilter: const ColorFilter.mode(Colors.black, BlendMode.srcIn),
|
||||
colorFilter: ColorFilter.mode(
|
||||
_isShiny ? Colors.yellow[700]! : Colors.black,
|
||||
BlendMode.srcIn
|
||||
),
|
||||
child: Image.network(_currentPokemon!.imageUrl, fit: BoxFit.contain),
|
||||
),
|
||||
),
|
||||
@ -174,12 +238,12 @@ class _GuessPageState extends State<GuessPage> {
|
||||
color: const Color(0xFF1B2333),
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: const Text(
|
||||
"WHO'S THAT POKÉMON?",
|
||||
child: Text(
|
||||
_isShiny ? "✨ SHINY POKÉMON DETECTED! ✨" : "WHO'S THAT POKÉMON?",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 22,
|
||||
color: _isShiny ? Colors.yellow[400] : Colors.white,
|
||||
fontSize: _isShiny ? 18 : 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2,
|
||||
),
|
||||
@ -275,10 +339,39 @@ class _GuessPageState extends State<GuessPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Score Display
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withAlpha(153),
|
||||
border: Border.all(color: Colors.black12),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
"CURRENT SCORE",
|
||||
style: TextStyle(color: Colors.black54, fontSize: 14, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
"$_currentScore",
|
||||
style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold, color: Color(0xFF3B6EE3)),
|
||||
),
|
||||
const Divider(height: 24),
|
||||
Text(
|
||||
"PERSONAL BEST: $_bestScore",
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@ -15,7 +15,6 @@ class _MainPageState extends State<MainPage> {
|
||||
final List<Widget> _pages = [
|
||||
const PokemonListPage(),
|
||||
const GuessPage(),
|
||||
const Center(child: Text("TRAINER PAGE placeholder")),
|
||||
const Center(child: Text("SYSTEM PAGE placeholder")),
|
||||
];
|
||||
|
||||
@ -34,12 +33,20 @@ class _MainPageState extends State<MainPage> {
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(26),
|
||||
child: _pages[_currentIndex],
|
||||
child: IndexedStack(
|
||||
index: _currentIndex,
|
||||
children: _pages,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
),
|
||||
bottomNavigationBar: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
),
|
||||
child: BottomNavigationBar(
|
||||
currentIndex: _currentIndex,
|
||||
onTap: (index) {
|
||||
setState(() {
|
||||
@ -58,16 +65,13 @@ class _MainPageState extends State<MainPage> {
|
||||
icon: Icon(Icons.games),
|
||||
label: 'GUESS',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.person),
|
||||
label: 'TRAINER',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.settings),
|
||||
label: 'SYSTEM',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,10 +135,14 @@ class _PokemonDetailPageState extends State<PokemonDetailPage> {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
Expanded(
|
||||
child: Text(
|
||||
pokemon.formatedName.toUpperCase(),
|
||||
style: const TextStyle(color: Colors.white, fontSize: 22, fontWeight: FontWeight.bold, letterSpacing: 2),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Row(
|
||||
children: [
|
||||
PokemonTypeWidget(pokemon.type1),
|
||||
|
||||
@ -14,62 +14,76 @@ class PokemonListPage extends StatefulWidget {
|
||||
class _PokemonListPageState extends State<PokemonListPage> {
|
||||
String _filter = 'ALL'; // ALL, CAUGHT, NEW
|
||||
int _caughtCount = 0;
|
||||
List<Pokemon> _allPokemon = [];
|
||||
List<Pokemon> _filteredPokemon = [];
|
||||
bool _isSyncing = false;
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadPokemonData();
|
||||
PokedexDatabase.onDatabaseUpdate.addListener(_loadPokemonData);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
PokedexDatabase.onDatabaseUpdate.removeListener(_loadPokemonData);
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _loadPokemonData() async {
|
||||
setState(() => _isSyncing = true);
|
||||
|
||||
final count = await PokedexDatabase.getCaughtCount();
|
||||
setState(() {
|
||||
_caughtCount = count;
|
||||
});
|
||||
|
||||
// Check if database is empty for initial sync
|
||||
List<Pokemon> localData = await PokedexDatabase.getPokemonList();
|
||||
if(localData.isEmpty) {
|
||||
try {
|
||||
final List<Pokemon> remoteData = await PokemonApi.getAllPokemon();
|
||||
// Insert first 151
|
||||
// Insert all
|
||||
for (var p in remoteData) {
|
||||
if(p.id > 151) break;
|
||||
await PokedexDatabase.insertPokemon(p);
|
||||
}
|
||||
localData = await PokedexDatabase.getPokemonList();
|
||||
} catch (e) {
|
||||
debugPrint(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by ID to ensure order
|
||||
localData.sort((a, b) => a.id.compareTo(b.id));
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
setState(() {
|
||||
_allPokemon = localData;
|
||||
_caughtCount = count;
|
||||
_applyFilter();
|
||||
_isSyncing = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _applyFilter() {
|
||||
setState(() {
|
||||
if (_filter == 'ALL') {
|
||||
_filteredPokemon = _allPokemon;
|
||||
} else if (_filter == 'CAUGHT') {
|
||||
_filteredPokemon = _allPokemon.where((p) => p.isCaught).toList();
|
||||
}
|
||||
});
|
||||
|
||||
// Reset scroll position to top when filter changes
|
||||
if (_scrollController.hasClients) {
|
||||
_scrollController.jumpTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildPokemonTile(BuildContext context, int index) {
|
||||
return FutureBuilder<Pokemon?>(
|
||||
future: PokedexDatabase.getPokemon(index + 1),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData || snapshot.data == null) {
|
||||
return const SizedBox(
|
||||
height: 90,
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
final pokemon = snapshot.data!;
|
||||
|
||||
// Apply filter logic
|
||||
if (_filter == 'CAUGHT' && !pokemon.isCaught) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
if (_filter == 'NEW' && pokemon.isCaught) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final pokemon = _filteredPokemon[index];
|
||||
return PokemonTile(pokemon);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -89,7 +103,7 @@ class _PokemonListPageState extends State<PokemonListPage> {
|
||||
children: [
|
||||
Icon(Icons.menu, color: Colors.black87),
|
||||
Text(
|
||||
'LIST - KANTO',
|
||||
'LIST - NATIONAL',
|
||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold, letterSpacing: 2),
|
||||
),
|
||||
Icon(Icons.search, color: Colors.black87),
|
||||
@ -104,7 +118,6 @@ class _PokemonListPageState extends State<PokemonListPage> {
|
||||
children: [
|
||||
_buildTab('ALL', _filter == 'ALL'),
|
||||
_buildTab('CAUGHT', _filter == 'CAUGHT'),
|
||||
_buildTab('NEW', _filter == 'NEW'),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -119,7 +132,7 @@ class _PokemonListPageState extends State<PokemonListPage> {
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'${_caughtCount.toString().padLeft(3, '0')} / 151',
|
||||
'${_caughtCount.toString().padLeft(3, '0')} / ${_allPokemon.length}',
|
||||
style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const Text(
|
||||
@ -146,9 +159,27 @@ class _PokemonListPageState extends State<PokemonListPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_isSyncing && _allPokemon.isEmpty)
|
||||
const Center(child: CircularProgressIndicator())
|
||||
else if (_filteredPokemon.isEmpty)
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.search_off, size: 64, color: Colors.black26),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'NO POKEMON FOUND IN $_filter',
|
||||
style: const TextStyle(color: Colors.black45, fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
else
|
||||
ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.all(12),
|
||||
itemCount: 151,
|
||||
itemCount: _filteredPokemon.length,
|
||||
itemBuilder: _buildPokemonTile,
|
||||
),
|
||||
],
|
||||
@ -161,7 +192,7 @@ class _PokemonListPageState extends State<PokemonListPage> {
|
||||
color: const Color(0xFF1B2333),
|
||||
alignment: Alignment.center,
|
||||
child: const Text(
|
||||
'KANTO REGIONAL POKEDEX V2.0',
|
||||
'NATIONAL POKEDEX V2.0',
|
||||
style: TextStyle(color: Colors.white70, fontSize: 12, letterSpacing: 1),
|
||||
),
|
||||
),
|
||||
@ -174,9 +205,10 @@ class _PokemonListPageState extends State<PokemonListPage> {
|
||||
return Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
if (_filter != title) {
|
||||
_filter = title;
|
||||
});
|
||||
_applyFilter();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
|
||||
@ -5,10 +5,12 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import shared_preferences_foundation
|
||||
import sqflite_darwin
|
||||
import sqlite3_flutter_libs
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
PODS:
|
||||
- FlutterMacOS (1.0.0)
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqflite_darwin (0.0.4):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@ -31,6 +34,7 @@ PODS:
|
||||
|
||||
DEPENDENCIES:
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||
|
||||
@ -41,6 +45,8 @@ SPEC REPOS:
|
||||
EXTERNAL SOURCES:
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
shared_preferences_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||
sqflite_darwin:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
||||
sqlite3_flutter_libs:
|
||||
@ -48,6 +54,7 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: 8d708bc63e9f4ce48f0ad9d6269e478c5ced1d9b
|
||||
sqlite3_flutter_libs: d13b8b3003f18f596e542bcb9482d105577eff41
|
||||
|
||||
@ -25,6 +25,7 @@ dependencies:
|
||||
http: ^1.1.0
|
||||
cupertino_icons: ^1.0.2
|
||||
google_fonts: ^8.0.2
|
||||
shared_preferences: ^2.5.4
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user