Commit a51d34d9 by Rafa Castillo Passols

Añadido cambios de los records

parents de48da35 aaf9d98d
......@@ -44,3 +44,6 @@ app.*.map.json
/android/app/profile
/android/app/release
/android/app/.cxx
# Manual
./pubspec.lock
......@@ -4,4 +4,23 @@ class PeponatorRecord {
final DateTime fecha;
PeponatorRecord({required this.jugador, required this.puntuacion, required this.fecha});
factory PeponatorRecord.desdeJson(Map<String, dynamic> json) {
return PeponatorRecord(
jugador: json['jugador'],
puntuacion: json['puntuacion'],
fecha: DateTime.parse(json['fecha'])
);
}
String aJson(){
var json = '''
{
"jugador": "$jugador",
"puntuacion": $puntuacion,
"fecha": "$fecha"
}
''';
return json;
}
}
\ No newline at end of file
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:peponator/modelo/dificultad.dart';
import 'package:peponator/modelo/peponator_record.dart';
import 'package:peponator/modelo/pista.dart';
import 'package:peponator/paginas/paginas.dart';
import 'package:peponator/widgets/pantalla_pausa.dart';
import 'package:peponator/widgets/peponator_mensaje.dart';
import 'dart:math';
......@@ -10,19 +15,10 @@ import 'package:peponator/widgets/tu_mensaje.dart';
// TODO: PantallaJuego debería introducirse en una vista PageStorage para almacenar el estado del scrollController
/// A la pantalla de juego se le pasa una dificultad y genera
/// una partida que irá registrando la puntuación, que depende
/// de cosas como la dificultad, el número de intentos o las
/// pistas dadas
class PantallaJuego extends StatefulWidget {
final bool fromHome;
final Dificultad dificultad;
const PantallaJuego({
required super.key,
required this.fromHome,
required this.dificultad
});
const PantallaJuego({Key? key, required this.fromHome}): super(key: key);
@override
State<PantallaJuego> createState() => _PantallaJuegoState();
......@@ -31,6 +27,7 @@ class PantallaJuego extends StatefulWidget {
class _PantallaJuegoState extends State<PantallaJuego>
with SingleTickerProviderStateMixin {
late final TextEditingController textController = TextEditingController();
late final TextEditingController recordTextController = TextEditingController();
late final ScrollController scrollController = ScrollController();
late final AnimationController _controller;
......@@ -59,13 +56,28 @@ class _PantallaJuegoState extends State<PantallaJuego>
late bool espera;
late bool victoria;
late int puntuacion;
late int posicion;
late String jugador;
late final File recordsFile;
List<PeponatorRecord>? records;
@override
void initState() {
super.initState();
_loadRecords();
// TODO: Cargar el máximo de intentos
maxIntentos = 21;
recordTextController.addListener(() =>
setState(() {
jugador = recordTextController.text;
})
);
_controller = AnimationController(
duration: Duration(milliseconds: 200),
vsync: this
......@@ -124,10 +136,21 @@ class _PantallaJuegoState extends State<PantallaJuego>
error = false;
espera = false;
victoria = false;
puntuacion = 0;
posicion = PantallaRecords.maxRecords;
jugador = "";
});
}
@override
void dispose() {
textController.dispose();
recordTextController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return OrientationBuilder(
builder: (context, orientation) {
......@@ -627,10 +650,135 @@ class _PantallaJuegoState extends State<PantallaJuego>
);
}
// TODO: Agregar una pantalla de registro de récords
Widget _buildPantallaFinal(Orientation orientation){
final fullWidth = MediaQuery.of(context).size.width;
final fullHeight = 380.0;
final fullWidth = (orientation == Orientation.portrait)?
MediaQuery.of(context).size.width - MediaQuery.of(context).padding.horizontal : 400.0;
final fullHeight = (orientation == Orientation.portrait)?
380.0 : MediaQuery.of(context).size.height - MediaQuery.of(context).padding.vertical;
if(victoria && posicion < PantallaRecords.maxRecords){
return SizedBox(
width: fullWidth,
height: fullHeight,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Column(
children: [
Text(
puntuacion.toString(),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 16.0),
Text(
(posicion == 0)? '¡Esta es tu mejor puntuación!' : 'Esta es tu ${posicion+1}ª mejor puntuación',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Introduce aquí tu nombre:',
style: Theme.of(context).textTheme.bodyLarge,
),
TextField(
controller: recordTextController,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
maxLength: 10,
decoration: InputDecoration(
hintText: 'Tu nombre...',
border: OutlineInputBorder(),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 5.0
)
),
errorText: (jugador.isEmpty)? '' : null,
errorStyle: TextStyle(
fontSize: 0
)
),
)
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: TextButton(
style: TextButton.styleFrom(
backgroundColor: Color.fromARGB(255, 0, 86, 3),
foregroundColor: Colors.white,
disabledBackgroundColor: Colors.black26,
disabledForegroundColor: Color.fromARGB(255, 40, 40, 40),
),
onPressed: (jugador.isNotEmpty)? () {
final newRecord = PeponatorRecord(
jugador: jugador,
puntuacion: puntuacion,
fecha: DateTime.now()
);
records!.insert(posicion, newRecord);
while(records!.length > PantallaRecords.maxRecords){
records!.removeLast();
}
_writeRecords();
setState(() {
posicion = PantallaRecords.maxRecords;
});
} : null,
child: Text(
'Guardar récord',
textScaler: TextScaler.linear(1.1),
)
),
)
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: TextButton(
style: TextButton.styleFrom(
backgroundColor: Color.fromARGB(255, 150, 10, 0),
foregroundColor: Colors.white,
disabledBackgroundColor: Colors.black26,
disabledForegroundColor: Color.fromARGB(255, 40, 40, 40),
),
onPressed: () {
setState(() {
posicion = PantallaRecords.maxRecords;
});
},
child: Text(
'Salir sin guardar',
textScaler: TextScaler.linear(1.1),
)
),
)
)
],
)
],
),
),
);
}
return SizedBox(
width: fullWidth,
......@@ -650,7 +798,7 @@ class _PantallaJuegoState extends State<PantallaJuego>
),
const SizedBox(height: 16.0),
Text(
victoria? '¿Quieres jugar otra vez?' : 'Más suerte la próxima vez...',
victoria? 'Puntuación: $puntuacion' : 'Más suerte la próxima vez...',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
......@@ -811,7 +959,7 @@ class _PantallaJuegoState extends State<PantallaJuego>
void _escribirRespuesta() async {
await Future.delayed(Duration(milliseconds: 600));
setState(() {
// TODO: Construir respuesta de Peponator con cierto retardo
// TODO: Construir respuesta de Peponator
mensajes.add(PeponatorMensaje(message: "¡Hola! Estoy pensando en un número del $limiteInferior al $limiteSuperior. ¿Te crees capaz de adivinarlo?"));
if(numeroEscogido! < numeroAdivinar){
limiteInferior = numeroEscogido! + 1;
......@@ -823,6 +971,16 @@ class _PantallaJuegoState extends State<PantallaJuego>
}
if(numeroEscogido! == numeroAdivinar){
victoria = true;
// TODO: Calcular puntuación
puntuacion = 1500;
if(records != null){
posicion = records!.length;
while(posicion > 0 && records![posicion-1].puntuacion < puntuacion){
posicion--;
}
}
}
numeroEscogido = null;
intentos++;
......@@ -837,6 +995,40 @@ class _PantallaJuegoState extends State<PantallaJuego>
_scrollDown();
});
}
Future<void> _loadRecords() async {
recordsFile = await PantallaRecords.localFile();
final lista = <PeponatorRecord>[];
try {
final productosString = await recordsFile.readAsString();
print(productosString);
final List<dynamic> recordsJson = jsonDecode(productosString);
for (var prodJson in recordsJson) {
lista.add(PeponatorRecord.desdeJson(prodJson));
}
} on FileSystemException catch(e) {
lista.clear();
}
finally {
records = lista;
}
}
Future<void> _writeRecords() async {
final sb = StringBuffer('[\n');
for(int i = 0; i<records!.length; i++) {
sb.write(records![i].aJson());
if (i<records!.length-1) {
sb.write(',\n');
} else {
sb.write('\n');
}
}
sb.write(']');
await recordsFile.writeAsString(sb.toString());
}
}
enum OpcionesFinPartida {
......
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:peponator/modelo/modelo.dart';
class PantallaRecords extends StatelessWidget {
class PantallaRecords extends StatefulWidget {
static const int maxRecords = 20;
const PantallaRecords({super.key});
@override
Widget build(BuildContext context) {
// TODO: Cargar los récords (esto se haría con un archivo de texto en la carpeta privada de la aplicación)
final records = <PeponatorRecord>[];
records.add(PeponatorRecord(
jugador: "AAA",
puntuacion: 12211350,
fecha: DateTime.now()
));
records.add(PeponatorRecord(
jugador: "BBB",
puntuacion: 25,
fecha: DateTime.now()
));
records.add(PeponatorRecord(
jugador: "CCC",
puntuacion: 13,
fecha: DateTime.now()
));
records.add(PeponatorRecord(
jugador: "DDD",
puntuacion: 7,
fecha: DateTime.now()
));
records.add(PeponatorRecord(
jugador: "EEE",
puntuacion: 6,
fecha: DateTime.now()
));
records.add(PeponatorRecord(
jugador: "FFF",
puntuacion: 5,
fecha: DateTime.now()
));
records.add(PeponatorRecord(
jugador: "GGG",
puntuacion: 4,
fecha: DateTime.now()
));
records.add(PeponatorRecord(
jugador: "HHH",
puntuacion: 3,
fecha: DateTime.now()
));
State<PantallaRecords> createState() => _PantallaRecordsState();
static Future<String> _localPath() async {
final Directory directory = await getApplicationDocumentsDirectory();
return directory.path;
}
static Future<File> localFile() async {
final path = await _localPath();
return File('$path/records.json');
}
}
class _PantallaRecordsState extends State<PantallaRecords> {
@override
Widget build(BuildContext context) {
return OrientationBuilder(builder: (context, orientation) {
return Scaffold(
body: SafeArea(
child: LayoutBuilder(
child: FutureBuilder(
future: _loadRecords(),
builder: (context, AsyncSnapshot<List<PeponatorRecord>> snapshot) {
if(snapshot.connectionState == ConnectionState.done){
return LayoutBuilder(
builder: (context, constraints) {
if(orientation == Orientation.portrait){
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
_buildTitle(context, orientation),
_buildRecordsView(context, orientation, snapshot.requireData)
],
);
}
else{
return Row(
children: [
SizedBox(
height: constraints.maxHeight,
width: constraints.maxWidth/4,
child: _buildTitle(context, orientation),
),
SizedBox(
height: constraints.maxHeight,
width: constraints.maxWidth*3/4,
child: _buildRecordsView(context, orientation, snapshot.requireData),
)
],
);
}
}
);
}
else{
return const Center(child: CircularProgressIndicator(),);
}
}
)
),
floatingActionButton: _buildFAB(context, orientation),
);
});
}
Widget _buildTitle(BuildContext context, Orientation orientation){
return Container(
color: Theme.of(context).colorScheme.primary,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
......@@ -84,9 +104,14 @@ class PantallaRecords extends StatelessWidget {
],
),
)
),
if(records.isNotEmpty) Expanded(
child: ListView.builder(
);
}
Widget _buildRecordsView(BuildContext context, Orientation orientation, List<PeponatorRecord> records){
if(records.isNotEmpty) {
final vistaRecords = ListView.builder(
shrinkWrap: true,
itemCount: records.length,
itemBuilder: (context, index){
Color c = Theme.of(context).colorScheme.inversePrimary;
Color? t = Theme.of(context).textTheme.titleLarge?.color;
......@@ -164,26 +189,40 @@ class PantallaRecords extends StatelessWidget {
),
);
},
shrinkWrap: true,
itemCount: records.length,
)
)
else Expanded(
child: Center(
);
if(orientation == Orientation.portrait){
return Expanded(
child: vistaRecords
);
}
else{
return vistaRecords;
}
}
else {
final message = Center(
child: Text(
'No hay ningún récord registrado de momento.\n\n¡Juega y registra el primero!',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
)
),
)
],
);
if(orientation == Orientation.portrait){
return Expanded(
child: message,
);
}
)
),
floatingActionButton: Align(
alignment: Alignment.bottomCenter,
else{
return message;
}
}
}
Widget _buildFAB(BuildContext context, Orientation orientation){
return Align(
alignment: (orientation == Orientation.portrait)? Alignment.bottomCenter : Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(left: 32.0),
child: FloatingActionButton.extended(
......@@ -198,7 +237,10 @@ class PantallaRecords extends StatelessWidget {
style: Theme.of(context).textTheme.titleLarge,
)),
content: Text(
'Esta acción no se puede deshacer. ¿Seguro que quieres borrar todos los récords?',
(orientation == Orientation.portrait)?
'Esta acción no se puede deshacer. ¿Seguro que quieres borrar todos los récords?':
'Esta acción no se puede deshacer.\n¿Seguro que quieres borrar todos los récords?'
,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
),
......@@ -206,6 +248,7 @@ class PantallaRecords extends StatelessWidget {
actions: [
TextButton(
onPressed: () {
_deleteRecords();
Navigator.pop(context);
},
style: TextButton.styleFrom(
......@@ -214,11 +257,14 @@ class PantallaRecords extends StatelessWidget {
width: 2.0
)
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Text(
'Sí',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Theme.of(context).colorScheme.primary
),
),
)
),
TextButton(
......@@ -228,11 +274,14 @@ class PantallaRecords extends StatelessWidget {
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.primary
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Text(
'No',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Theme.of(context).colorScheme.onPrimary
),
),
)
)
],
......@@ -249,7 +298,30 @@ class PantallaRecords extends StatelessWidget {
),
),
),
),
);
}
Future<List<PeponatorRecord>> _loadRecords() async {
final file = await PantallaRecords.localFile();
final lista = <PeponatorRecord>[];
try {
final productosString = await file.readAsString();
print(productosString);
final List<dynamic> recordsJson = jsonDecode(productosString);
for (var prodJson in recordsJson) {
lista.add(PeponatorRecord.desdeJson(prodJson));
}
} on FileSystemException catch(e) {
lista.clear();
}
return lista;
}
Future<void> _deleteRecords() async {
final file = await PantallaRecords.localFile();
await file.delete();
setState(() {});
}
}
\ No newline at end of file
......@@ -5,8 +5,10 @@
import FlutterMacOS
import Foundation
import path_provider_foundation
import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
}
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
url: "https://pub.dev"
source: hosted
version: "2.12.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
characters:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
version: "1.4.0"
clock:
dependency: transitive
description:
name: clock
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev"
source: hosted
version: "1.1.2"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.1"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
version: "1.0.8"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
url: "https://pub.dev"
source: hosted
version: "1.3.2"
ffi:
dependency: transitive
description:
name: ffi
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
file:
dependency: transitive
description:
name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
url: "https://pub.dev"
source: hosted
version: "7.0.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
url: "https://pub.dev"
source: hosted
version: "5.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
url: "https://pub.dev"
source: hosted
version: "10.0.8"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
url: "https://pub.dev"
source: hosted
version: "3.0.9"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
url: "https://pub.dev"
source: hosted
version: "5.1.1"
matcher:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
version: "0.12.17"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev"
source: hosted
version: "1.16.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
url: "https://pub.dev"
source: hosted
version: "2.3.0"
platform:
dependency: transitive
description:
name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
url: "https://pub.dev"
source: hosted
version: "3.1.6"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.8"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5"
url: "https://pub.dev"
source: hosted
version: "2.5.3"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: c2c8c46297b5d6a80bed7741ec1f2759742c77d272f1a1698176ae828f8e1a18
url: "https://pub.dev"
source: hosted
version: "2.4.9"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
url: "https://pub.dev"
source: hosted
version: "2.5.4"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
url: "https://pub.dev"
source: hosted
version: "2.4.3"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_span:
dependency: transitive
description:
name: source_span
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
url: "https://pub.dev"
source: hosted
version: "1.10.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.dev"
source: hosted
version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.dev"
source: hosted
version: "1.4.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.dev"
source: hosted
version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
url: "https://pub.dev"
source: hosted
version: "0.7.4"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
url: "https://pub.dev"
source: hosted
version: "14.3.1"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
sdks:
dart: ">=3.7.0 <4.0.0"
flutter: ">=3.27.0"
......@@ -35,6 +35,7 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
shared_preferences: ^2.5.3
path_provider: ^2.1.5
dev_dependencies:
flutter_test:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment