Aplicación multiplataforma en Ionic y VUE 3
Objetivos
En este proyecto he querido mostrar cómo cualquier desarrollador Web es capaz, aunque no lo sepa, de desarrollar aplicaciones multiplataforma con el mismo código base.
Pudiendo, además, aprovechar las características del sistema que ejecuta la aplicación, tales como la cámara, sistema de archivos, apps externas, sensores, etc.
Ionic y Capacitor
¿Qué es Capacitor?
Capacitor es una herramienta que nos permite encapsular dentro de un proyecto java, un proyecto únicamente web. Permitiéndonos utilizar el IDE: Android Studio para ejecutar un build y exportar la aplicación como .apk.
Adicionalmente también podemos desarrollar para ios, para lo cual deberemos utilizar el proyecto el Swift y realizar el build en un ordenador MacOS.
Esta herramienta fue creada y es mantenida por Ionic, creadores a su vez del framework Ionic.
¿Qué es Ionic?
Como hemos comentado, Ionic es un framework. Esto significa que ofrece todo lo necesario para crear aplicaciones.
Con esta herramienta nos aseguramos de que, al exportar un proyecto con Capacitor, toda la lógica y elementos HTML serán compatibles cuando se utilice nuestra aplicación en cualquier dispositivo.
Esto no nos impide utilizar frameworks externos como, en este caso, Vue, para desarrollar nuestra aplicación. Únicamente deberemos de tener cuidado con ciertos elementos, en esos casos deberemos de utilizar los que nos proveídos por Ionic.
Vue 3
Vue 3 es la última iteración de Vue. En Vue 3 tenemos la disponibilidad de utilizar la nueva Composition API, en vez de la antigua Options API (todavía ampliamente utilizada).
Con esta nueva sintaxis podemos crear componentes muy fácilmente:
Puntos clave
Estructura
Esta será la estructura final del proyecto, iremos desglosando paso por paso cómo reproducir la aplicación:
Requisitos
- Necesitaremos Node.js.
- Instalamos Ionic CLI y las utilidades necesarias para utilizarlo de forma global:
- npm install -g @ionic/cli@latest native-run cordova-res
- Creamos un nuevo proyecto utilizando la CLI de Ionic:
- ionic start photo-gallery tabs –type vue –capacitor
- Instalamos las dependencias de capacitor necesarias:
- npm install @capacitor/camera @capacitor/preferences @capacitor/filesystem @ionic/pwa-elements
- Con esto ya temenos un template que podemos ejecutar con el comando: ionic serve
Partiendo del template, iremos programando en JavaScript toda la funcionalidad.
Implementar las pantallas
Layout
Primero, vamos a crear un layout compartido para todas las pantallas, de esta forma podemos añadir tantas pantallas como queramos que todas compartirán el mismo layout.
Como podemos ver, en este componente hacemos uso de: <ion-router-outlet></ion-router-outlet>
.
Éste cumple la misma función que el elemento <router-view></ router-view >
de Vue. Éste nos permite inyectar cualquier tipo de componente hijo definido en el router, en el lugar en el que hayamos definido el elemento:
Aquí definimos los hijos de /tabs/, serán los tabs que utilizaremos para cada pantalla de la aplicación (Tab1 y Tab2).
Todos ellos compartirán el mismo diseño, ya que son encapsulados por el código que hayamos escrito en TabsLayout.
Implementación de la pantalla de cámara
Para implementar la pantalla de cámara nos centraremos en dos archivos: Tab1View.vue (UI) y usePhotoGallery.js (hook con la lógica).
Interfaz
Lógica
Como podemos ver, importamos las dependencias necesarias para utilizar la cámara, el sistema de archivos, el hook para comprobar si estamos en web o en un dispositivo móvil (isPlatform) y los modales para informar al usuario del estado de la aplicación (alertController, loadingController).
En este caso vamos a omitir la captura del código, ya que encontraréis el link al repositorio con el código al final de este post, pero os voy a dejar una captura de la estructura del hook:
Cuando queramos utilizar el hook, deberemos de llamarlo de la siguiente forma:
const {photos, takePhoto, deletePhoto, controlLoadingScreen} = usePhotoGallery();
Como podemos comprobar, la sintaxis es similar a la utilizada con los hooks de React (componentes funcionales) o Vue.
Pantalla explorador de archivos
Interfaz android
Interfaz web
Implementación de la interfaz
Para ahorrar espacio en el post, voy a centrarme en el código JavaScript y omitir los estilos aplicados:
Lo primero que nos encontramos en el template es el elemento ion-header.
Dentro de este elemento tenemos el botón back, el cual estará deshabilitado si estamos en la carpeta root que usará la aplicación dentro del sistema de archivos (en /DOCUMENTS).
Como veremos más adelante, ROOT_FOLDER será “my-photo-collections”.
Los siguientes elementos serán dos inputs no visibles, estos inputs los utilizaremos para simular a la interacción con el usuario para subir documentos y carpetas (sólo en web).
El flow sería el siguiente:
De esta forma no mostramos inputs type file, sino buttons que representan el click de dichos inputs.
En este punto vamos a mostrar el componente FolderContent:
Por último, necesitamos que el usuario pueda añadir carpetas y archivos. Para ello implementamos unos simples botones de Ionic que desplieguen una lista vertical de opciones.
Esto se consigue envolviendo uno o varios botones <ionic-button> con <ion-fab-list>
:
Implementación de la lógica
Antes de nada, vamos a crear nuestro propio hook con utilidades que podamos reutilizar. Para ello haremos una función con y exportaremos las variables y métodos declarados dentro de ella para importarlos desde otros archivos.
Estos hooks los crearemos en la carpeta /composables.
Empecemos por useUtils.js.
En este hook tendremos utilidades relacionadas con archivos y carpetas:
La función mkdirHelper nos permitirá crear cualquier carpeta pasándole una ruta, si la carpeta ya existe, nos devolverá false y mostrará el error en la consola.
La función checkRootFolder comprobará si la carpeta ROOT_FOLDER (definida en el archivo Global.js) existe. Sino existe, se muestra un mensaje al usuario indicándole qué carpeta se va a crear y dónde la puede encontrar:
Por último, necesitaremos una función para convertir blobs (archivos del sistema) en string en base64:
Ahora pasaremos al archivo FileExplorer.vue. Este archivo es bastante extenso, con lo cual, omitiré algunas partes para simplificarlo.
Todo el código lo podréis encontrar en mi repositorio de GitHub: https://github.com/host4ideas/proyecto-video-post-FMB
Como se está utilizando Vue 3 con la sintaxis <script setup>. Vamos a crear variables reactivas para poder actualizar la vista de archivos y carpetas cada vez que haya algún cambio en ellos.
Esta reactividad la encontraremos al final del archivo, donde creamos un watch de Vue para llamar a la función loadDocuments cada vez que los datos cambian.
Esta sería la función loadDocuments, la cual carga los archivos y carpetas de la ruta actual (la ruta la recogemos por props gracias al router):
Como hemos implementado un botón de ir hacia atrás, dicho botón debe de ir adherido a funcionalidad customizada, en este caso no nos vale con ir hacia atrás en el historial.
¿Pero por qué?
La respuesta es la siguiente:
Imaginemos que te encuentras en la carpeta test1:
ROOT_FOLDER/test/test1
Si pulsas el botón hacia atrás y vuelves hasta ROOT_FOLDER, deberemos de comprobar que no hay más carpetas padres, de lo contrario, el usuario podría ir hacia atrás en el historial hasta salir de nuestra app (esto sería perjudicial sobre todo en dispositivos móviles).
Para ello:
Vamos a dejar el post en este punto, ya que el objetivo de este post es explicar cómo podéis replicar la funcionalidad de esta aplicación vosotros mismos.
¿Cómo puedo adaptar esto en mi proyecto?
Para adaptar la funcionalidad de esta aplicación para vuestros propios fines, simplemente entrad en el repositorio de GitHub y copiad la funcionalidad. Me he esmerado en que sea modular y no funcione únicamente en este proyecto (la única dependencia es que sea un proyecto Vue y tener la carpeta actual del usuario en una variable currentFolder).
Aquí vamos a terminar por hoy, si os han quedado más dudas podéis contactar conmigo a través de:
LinkedIn: https://www.linkedin.com/in/felix-martinez-bendicho/
Datos de interés
- Autor: Félix Martínez Bendicho
- Curso: Desarrollo Web Full Stack + Multicloud con Azure y AWS
- Centro: Tajamar
- Año académico: 2022-2023
- Repositorio: https://github.com/host4ideas/proyecto-video-post-FMB