Commit 6f38edde by Tecnicos

Sistema para añadir archivos y carpetas en estado funcional.

parent 97bd3290
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'paginas/pagina_principal.dart'; import 'paginas/pagina_principal.dart';
import 'package:prueba_multimedia/modelo/lista_seleccionables.dart';
class ConvertexPrototipoApp extends StatelessWidget { class ConvertexPrototipoApp extends StatelessWidget {
const ConvertexPrototipoApp({super.key}); const ConvertexPrototipoApp({super.key});
...@@ -18,7 +19,12 @@ class ConvertexPrototipoApp extends StatelessWidget { ...@@ -18,7 +19,12 @@ class ConvertexPrototipoApp extends StatelessWidget {
) )
), ),
themeMode: ThemeMode.system, themeMode: ThemeMode.system,
home: PaginaPrincipal(), home: MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => ListaSeleccionables())
],
child: PaginaPrincipal(),
),
); );
} }
} }
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:prueba_multimedia/modelo/seleccionable.dart';
class Archivo extends Seleccionable {
final File file;
// Mostrar nombre de archivo y no path
Archivo(this.file): super(file.path, Icon(Icons.description_outlined));
}
\ No newline at end of file
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:prueba_multimedia/modelo/seleccionable.dart';
class Carpeta extends Seleccionable {
final Directory directory;
final listaConvertibles = <Seleccionable>[];
final bool recursiva;
/**
* TODO: iterar sobre los archivos y carpetas teniendo en cuenta la
* recursividad
*/
Carpeta(this.directory, this.recursiva):
super(directory.path, const Icon(Icons.description_outlined)) {
var listaCarpeta = directory.list(recursive: recursiva);
}
}
\ No newline at end of file
import 'package:flutter/material.dart';
import 'package:prueba_multimedia/modelo/seleccionables.dart';
class ListaSeleccionables extends ChangeNotifier {
final _seleccionables = <Seleccionable>[];
List<Seleccionable> get seleccionables => List.unmodifiable(_seleccionables);
void borraSeleccionable(int indice) {
_seleccionables.removeAt(indice);
notifyListeners();
}
void addSeleccionable(Seleccionable item) {
_seleccionables.add(item);
notifyListeners();
}
}
\ No newline at end of file
import 'package:flutter/material.dart';
import 'package:prueba_multimedia/widget/action_button.dart';
/// Representa un item que se puede añadir a la lista
/// de conversión.
class Seleccionable {
final String nombre;
final Icon icono;
Seleccionable(this.nombre, this.icono);
}
\ No newline at end of file
import 'dart:io';
import 'package:flutter/material.dart';
/// Representa un item que se puede añadir a la lista
/// de conversión.
class Seleccionable {
final String nombre;
final Icon icono;
Seleccionable({required this.nombre, required this.icono});
}
/// Las carpetas son seleccionables que contienen otros seleccionables
class Carpeta extends Seleccionable {
final Directory directory;
final listaConvertibles = <Seleccionable>[];
final bool recursiva;
Carpeta(this.directory, this.recursiva): super(
nombre: directory.path,
icono: const Icon(Icons.description_outlined)
)
{
// TODO: mirar recursividad y Link objects
var listaCarpeta = directory.list(recursive: recursiva);
listaCarpeta.forEach( (entity) {
if (entity is File) {
listaConvertibles.add(Archivo(entity));
}
else if (entity is Directory) {
listaConvertibles.add(Carpeta(directory, false));
}
});
}
}
/// Seleccionables que pueden pasar por un proceso de conversion de formatos
class Convertible extends Seleccionable {
final String formatoInicial;
final String? formatoFinal;
Convertible({required super.nombre, required super.icono,
required this.formatoInicial, this.formatoFinal});
}
class Archivo extends Convertible {
final File file;
Archivo(this.file): super(
nombre: file.path.split('/').last,
icono: Icon(Icons.description_outlined),
formatoInicial: file.path.split('.').last,
formatoFinal: null
);
}
class Enlace extends Convertible {
final String enlace;
Enlace(this.enlace): super(
nombre: enlace,
icono: Icon(Icons.link_outlined),
formatoInicial: enlace,
formatoFinal: null
);
}
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:prueba_multimedia/widget/convertex_fab_bar.dart'; import 'package:prueba_multimedia/widget/convertex_fab_bar.dart';
import 'package:prueba_multimedia/modelo/lista_seleccionables.dart';
import 'pagina_principal_llena.dart'; import 'pagina_principal_llena.dart';
import 'pagina_principal_vacia.dart'; import 'pagina_principal_vacia.dart';
import 'dart:math';
class PaginaPrincipal extends StatefulWidget { class PaginaPrincipal extends StatelessWidget {
const PaginaPrincipal({super.key}); const PaginaPrincipal({super.key});
@override Widget _construirCuerpo(BuildContext context) {
State<PaginaPrincipal> createState() => _PaginaPrincipalState(); return Consumer<ListaSeleccionables>(
} builder: (context, manager, child) {
if (manager.seleccionables.isNotEmpty) {
/* return PaginaPrincipalLlena(listaSeleccionables: manager);
* Al igual que en la lista de la compra, tenemos un estado que son } else {
* los archivos seleccionados para realizar la conversión. return PaginaPrincipalVacia();
* }
* Ese estado es consultado por la pantalla principal para determinar }
* si );
*/ }
class _PaginaPrincipalState extends State<PaginaPrincipal> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
...@@ -29,8 +29,10 @@ class _PaginaPrincipalState extends State<PaginaPrincipal> { ...@@ -29,8 +29,10 @@ class _PaginaPrincipalState extends State<PaginaPrincipal> {
title: Text('Convertex Prototipo'), title: Text('Convertex Prototipo'),
backgroundColor: Theme.of(context).primaryColor, backgroundColor: Theme.of(context).primaryColor,
actions: [ actions: [
IconButton(onPressed: () { IconButton(
showDialog<void>( icon: Icon(Icons.settings_outlined),
onPressed: () {
showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
...@@ -39,49 +41,21 @@ class _PaginaPrincipalState extends State<PaginaPrincipal> { ...@@ -39,49 +41,21 @@ class _PaginaPrincipalState extends State<PaginaPrincipal> {
TextButton( TextButton(
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
child: const Text('CLOSE'), child: const Text('CLOSE'),
), )
], ]
); );
}, }
); );
}, }
icon: Icon(Icons.settings_outlined)) )
], ]
), ),
body: _construirCuerpo(context), body: _construirCuerpo(context),
floatingActionButton: Padding( floatingActionButton: Padding (
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: ConVertexFabBar() child: ConVertexFabBar()
), ),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
); );
} }
Widget _construirCuerpo(BuildContext context) {
if(false){
return PaginaPrincipalLlena();
}
else{
return PaginaPrincipalVacia();
}
/*return SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'No hay archivos seleccionados',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 16.0),
Text(
'Pulsa el botón + para agregarlos',
style: Theme.of(context).textTheme.bodyLarge,
)
],
),
)
);*/
}
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:prueba_multimedia/modelo/seleccionable.dart'; import 'package:prueba_multimedia/modelo/lista_seleccionables.dart';
import 'package:prueba_multimedia/modelo/seleccionables.dart';
import 'package:prueba_multimedia/widget/seleccionable_widget.dart'; import 'package:prueba_multimedia/widget/seleccionable_widget.dart';
class PaginaPrincipalLlena extends StatelessWidget { class PaginaPrincipalLlena extends StatelessWidget {
const PaginaPrincipalLlena({super.key}); final ListaSeleccionables listaSeleccionables;
const PaginaPrincipalLlena({super.key, required this.listaSeleccionables});
static const ejemplo = ["Hola", "Esto es una prueba", "Ayuda"];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final seleccionables = listaSeleccionables.seleccionables;
return Padding( return Padding(
padding: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(10.0),
child: ListView.separated( child: ListView.separated(
itemCount: ejemplo.length, itemCount: seleccionables.length,
separatorBuilder: (context, index) { separatorBuilder: (context, index) {
return const SizedBox(height: 8.0); return const SizedBox(height: 8.0);
}, },
itemBuilder: (context, index) { itemBuilder: (context, index) {
return SeleccionableWidget(key: key, seleccionable: null, ); return SeleccionableWidget(seleccionable: seleccionables[index]);
}, },
), ),
); );
......
...@@ -2,8 +2,11 @@ import 'dart:io'; ...@@ -2,8 +2,11 @@ import 'dart:io';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:prueba_multimedia/modelo/lista_seleccionables.dart';
import 'package:prueba_multimedia/modelo/seleccionables.dart';
import './action_button.dart'; import 'action_button.dart';
import 'expandable_fab.dart'; import 'expandable_fab.dart';
class ConVertexFabBar extends StatefulWidget { class ConVertexFabBar extends StatefulWidget {
...@@ -26,6 +29,8 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> { ...@@ -26,6 +29,8 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final manager = Provider.of<ListaSeleccionables>(context, listen: false);
return SizedBox( return SizedBox(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
height: (_agregarOpen || _convertirOpen)? MediaQuery.of(context).size.height : 56, height: (_agregarOpen || _convertirOpen)? MediaQuery.of(context).size.height : 56,
...@@ -46,7 +51,7 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> { ...@@ -46,7 +51,7 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [..._buildFABs()], children: [..._buildFABs(manager)],
), ),
) )
], ],
...@@ -72,7 +77,7 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> { ...@@ -72,7 +77,7 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> {
return buttons; return buttons;
} }
List<Widget> _buildFABs() { List<Widget> _buildFABs(ListaSeleccionables manager) {
final toRet = <Widget>[]; final toRet = <Widget>[];
// FAB con las opciones para convertir // FAB con las opciones para convertir
...@@ -113,7 +118,7 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> { ...@@ -113,7 +118,7 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> {
distance: 60, distance: 60,
icon: Icon(Icons.add), icon: Icon(Icons.add),
key: _agregarKey, key: _agregarKey,
children: _loadAgregarActionButtons(context), children: _loadAgregarActionButtons(context, manager),
), ),
SizedBox( SizedBox(
width: 56, width: 56,
...@@ -135,7 +140,10 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> { ...@@ -135,7 +140,10 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> {
return toRet; return toRet;
} }
List<Widget> _loadAgregarActionButtons(BuildContext context){ // TODO: TERMINAR MÉTODOS
List<Widget> _loadAgregarActionButtons(BuildContext context,
ListaSeleccionables manager)
{
final buttons = <Widget>[ final buttons = <Widget>[
ActionButton( ActionButton(
tipoBoton: ActionButtonTypes.enlace, tipoBoton: ActionButtonTypes.enlace,
...@@ -146,9 +154,9 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> { ...@@ -146,9 +154,9 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> {
onPressed: () async { onPressed: () async {
String? path = await FilePicker.platform.getDirectoryPath(); String? path = await FilePicker.platform.getDirectoryPath();
if (path != null) { if (path != null) {
// TODO: AÑADIR POSIBILIDAD RECURSIVIDAD
var directory = Directory(path); var directory = Directory(path);
} else { manager.addSeleccionable(Carpeta(directory, false));
} }
} }
), ),
...@@ -157,7 +165,8 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> { ...@@ -157,7 +165,8 @@ class _ConVertexFabBarState extends State<ConVertexFabBar> {
onPressed: () async { onPressed: () async {
FilePickerResult? result = await FilePicker.platform.pickFiles(); FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result != null) { if (result != null) {
String filePath = result.files.single.path!; File file = File(result.files.first.path!);
manager.addSeleccionable(Archivo(file));
} else { } else {
// //
} }
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:prueba_multimedia/modelo/seleccionable.dart'; import 'package:prueba_multimedia/modelo/seleccionables.dart';
class SeleccionableWidget extends StatelessWidget { class SeleccionableWidget extends StatelessWidget {
final Seleccionable seleccionable; final Seleccionable seleccionable;
SeleccionableWidget({super.key, required this.seleccionable}); const SeleccionableWidget({super.key, required this.seleccionable});
// TODO: ACTUALIZAR PARA MOSTRAR FORMATOS Y CAMBIOS
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(
...@@ -23,10 +24,6 @@ class SeleccionableWidget extends StatelessWidget { ...@@ -23,10 +24,6 @@ class SeleccionableWidget extends StatelessWidget {
seleccionable.nombre, seleccionable.nombre,
style: Theme.of(context).textTheme.bodyLarge style: Theme.of(context).textTheme.bodyLarge
), ),
Text(
'CAMBIAME',
style: Theme.of(context).textTheme.bodySmall
),
], ],
) )
), ),
......
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