Ionic Framework, PouchDB y Cloudant: la combinación perfecta totalmente expuesta parte 11


Esta es una continuación de la serie sobre desarrollo en móviles que comencé aquí. Les recomiendo comenzar a escribir el código fuente desde la parte 1 ya que no se publica el código para descarga.

Con la parte 10, podríamos decir que comienza una nueva etapa del código así que debemos empezar con las cosas interesantes. Primero planifiquemos las siguientes funciones:

  • Alertas ante nuevas noticias. Esto ya me lo habían pedido, y recién ahora tiene sentido incluirlo pues ya tenemos todas las herramientas. Según lo que hemos visto, al activar la replicación estamos controlando el evento ‘paused’ para indicar que la sincronización terminó y no hay nada nuevo por el momento, pero no nos dice nada si hubieron noticias nuevas. Para eso debemos controlar otro evento llamado ‘change’ que se genera por cada cambio en la base de datos local, aquí simplemente ubicamos cuando se trate de una nueva noticia y podríamos ya lanzar la notificación, teniendo cuidado pues durante la primera ejecución del programa todas serán noticias nuevas y no queremos una avalancha de alertas.
  • Agregar un mecanismo para registrar las noticias más leídas. Esto supondrá que grabemos en algún lado que hemos leído la noticia. Recordemos que este documento será sincronizado hacia el servidor y a todos los usuarios con la versión actual, lo cual no queremos así que veremos como hacer para que la sincronización sea controlada: que los registros generados por el usuario sean sincronizados con el servidor pero que a los demás usuarios solamente lleguen los documentos con las estadísticas. Igual funcionaría para un mecanismo para registrar “Likes” tipo Facebook.

Comencemos con las alertas para nuevas noticias, para eso necesitamos un plugin para Ionic que nos ayude a manejar las notificaciones locales. Esto se refiere a las mismas alertas que reciben cuando tienen un correo o algún otro cambio relevante. Hay que recalcar que son locales, puesto que los datos ya están en la base de datos; en las apps normalmente se da todo lo contrario, primero llega la notificación y luego se descarga la información, pero como nuestro modelo es “off-line first” no podemos confiarnos en la red.

Para hacer la cosa aún más fácil, instalemos el componente Ng-Cordova que encapsula el código necesario para manejar plugins, mediante el siguiente comando:


bower install ng-Cordova --save

El parámetro –save es para agregar este componente a la lista de dependencias.

Seguidamente, instalemos el plugin:

ionic plugin add https://github.com/katzer/cordova-plugin-local-notifications.git

Y listo, ahora hay que ver donde es el mejor lugar para detectar que se ha insertado una nueva noticia y ese lugar puede ser al detectar un cambio. Recordemos que al momento de replicar ya se genera un evento al detectar el fin de la replicación. Veamos el archivo services.js


db.replicate.from(remote,
{live:true,
retry:true})
.on('paused',changed);

Es bueno recordar aquí como es esto de los eventos de replicación:

  • Paused: indica solamente que la replicación ha parado. Como hemos establecido el parámetro live en true, significa que ya no hay mas cambios que sincronizar. Esto también significa que la replicación no ha recibido mas registros en un rato largo, lo que sucede a cada rato cuando la velocidad del internet es bastante lenta.
  • Complete: Si es que establecemos live en false, significa que la replicación se hará una sola vez y al terminar se generará el evento Complete.

Noten que si queremos asegurar que la base local está al día, quizá haya que hacer un mecanismo de control como establecer un registro con la fecha de ultima actualización. Además, la replicación manual puede servir si sabemos que los cambios son poco frecuentes o si queremos que sea el usuario final quien controle la actualización.

Bien, entonces regresando al código, cuando la replicación se completa o se para, se ejecuta la función “changed” que está definida así:


function changed(){
console.log('cambios en la base de datos');
if (!initiated)
{
initiated=true;
db.changes({live: true, since: 'now', include_docs: true})
.on('change', newNews);
};

};

Aquí lo que hacemos es verificar que la base de datos está inicializada y usamos una variable “initiated” para controlar que solamente una vez llamemos  a la función db.changes. Con db.changes lo que hacemos es verificar un evento mas: cuando se ha modificado algún registro en la base de datos. Cuando se detecte este cambio se ejecuta la función “newNews”.

NOTA: fijense bien la secuencia, primero se replica y luego se monitorea el evento cambios. Por lo tanto, la secuencia de datos será así: inicias la aplicación, sincronizas, cuando se completa, cada registro nuevo o modificado generará una alerta. De esta manera, las noticias antiguas no generarán alertas.

Ahora veamos la funcion newNews:


function newNews(change){
if (!change.deleted){
if (change.doc.tipo=="news")
$rootScope.$broadcast('db:newNews',{newsId:change.id,
newsTitle:change.doc.titular});
}
}; function newNews(change){
if (!change.deleted){
if (change.doc.tipo=="news")
$rootScope.$broadcast('db:newNews',{newsId:change.id,
newsTitle:change.doc.titular});
}
};

Bien, notarán que esta función toma un parámetro llamado change que es el documento que ha sido afectado. El documento puede haber sido borrado, creado o modificado. Si es borrado la propiedad change.deleted será verdadera. Si el documento es creado o modificado por ahora los trataremos como iguales pues tendríamos que revisar la fecha de creación en alguna propiedad.

En la línea 10 verificamos que no se trate de un documento borrado y seguidamente verificamos que el documento sea del tipo news, porque también hay documentos del tipo cat y esos no queremos que manden notificaciones. Si todo se cumple, mandamos un broadcast para que se genere el evento de generación de la notificacion. Para ver eso vamos al archivo app.js.


.run(function($rootScope,$state,$cordovaLocalNotification){
$rootScope.$on('db:newNews',function(event,args){
var id = new Date().getMilliseconds();
$cordovaLocalNotification.schedule({
id: id,
title: 'Super Datos',
text: args.newsTitle,
data: {
newsId: args.newsId,
newsTitle: args.newstitle
}
}).then(function (result) {
console.log('Notificación registrada');
});

$rootScope.$on('$cordovaLocalNotification:click', function (
event,
notification,
state) {
var datos = JSON.parse(notification.data);
$state.go('app.detail',{id:datos.newsId});
});
});
})

Aquí notarán que hemos agregado una sección .run() para manejar dos eventos en la aplicación: el primero el evento que generamos anteriormente para avisar que hay una nueva noticia y otro mas para el evento $cordovaLocalNotification:click, este último evento es el que se genera cuando un usuario hace click encima de la notificación, es decir, que cuando llegue la notificación, el usuario vera el aviso en su teléfono y al hacer click se abrirá la aplicación y se abrirá en el estado detalle para que pueda leer el contenido. Creo que estamos de acuerdo que mas complicado ha sido encontrar y fijar el evento que lanza la notificación que programarla, pero lo hago así por una razón: trato que todos los eventos sean manejados en el app.js para no tener problema luego para mantenerlos y gestionarlos, incluso trato que los broadcast estén aquí en la medida de lo posible, o en su defecto en el archivo services.js, nunca en un controlador.

Y listo, ya pueden probar su nuevo lector de noticias, y cada vez que tengan una nueva noticia o una noticia antigua ha sido actualizada, recibirán una notificación que les permitirá enterarse e ir directamente al nuevo contenido.

Recalco que esto no es una notificación tradicional, pues el contenido ya está en el teléfono y es la misma aplicación la que genera la notificación. Las apps conectadas que son las mas comunes, mandan la notificación por la red y recién hacen la recuperación de los datos, todo depende de como quieren que su app se comporte.

Finalmente, pueden jugar con más opciones de las notificaciones locales, como agregar un botón para que el app te recuerde leer una noticia dentro de 15 minutos, o poner una notificación cuando el app esté sincronizando y demás cosas. Todo queda en ustedes.


  1. 1 Ionic Framework, PouchDB y Cloudant: la combinación perfecta totalmente expuesta | Víctor Pease

    […] Part 11 […]




Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s



%d bloggers like this: