Sin categoría

Windows Phone | A partir de marzo desaparecen las Rooms (salas)

posterMe acaba de llegar un correo indicándome que a partir de marzo desaparecerán las Rooms (salas) en las que podíamos agrupar a personas para compartir notas, calendario, fotos y enviar mensajes entre todos. Parece una mala noticia pero, si nos atenemos a la información indicada por el equipo de Windows Phone, se están trabajando en nuevas características en Windows 10 y seguramente las Rooms serán sustituidas por algún otro elemento con mayores ventajas para todos nosotros. Por mi parte sí hacía buen uso de las Rooms para compartir información con mi familia y con unos pocos amigos afortunados de tener un Windows Phone.

¿Qué os parece?

 

rooms

 

Enjoy Windows Phone! 🙂

Windows Phone | ¿No puedes ejecutar los emuladores de Windows Phone en Windows 10?

poster Escenario

Desde hace tiempo me era imposible ejecutar los emuladores de Windows Phone ya que alguna actualización de Windows 10 me lo impedía, sin dar ningún error ni mensaje que me pudiera guiar. El problema es que se quedaban iniciando el sistema “Windows Phone OS is starting…” y así hasta el fin de los siglos.

Como no me satisface quedarme esperando que se arregle sólo, supuse que alguien se habría enfrentado a esta situación y, buscando encontré la solución en un foro que no he vuelto a localizar, así que vamos con la solución

Solución

Lo primero que vamos a hacer es abrir el Administrador de Hyper-V y, tras seleccionar un emulador de Windows Phone, iremos a “Virtual Switch Manager”

 hyper-v-manager

Una vez abierta la ventana de Virtual Switch Manager, buscamos el switch de Windwos Phone y lo eliminamos.

virtual-switch-manager

Ahora debemos ejecutar Visual Studio con permisos de administrador y ejecutar el emulador que, al menos en la primera vez tardará un poco más de lo habitual en cargar el sistema pero funcionará 🙂

visual-studio-administrator emulator-running

Enjoy coding! 🙂

Apache Cordova | Añadir aviso de carga de datos “loading” animado

En este artículo quiero compartir un nuevo tip sencillo para Apps desarrolladas con Apache Cordova o PhoneGap y no es otro que añadir un aviso de que se están cargando datos o un mensaje de loading para que el usuario esté al tanto de que se está realizando dicha operación mientras debe esperar. Esto además, nos puede servir para otras acciones como actualizaciones por cálculos, etc.

¿Por qué es tan importante un aviso de carga de datos?

poster Muchos desarrolladores obvian la inclusión de mensajes de aviso de carga de datos en sus Apps y, peor aún tampoco lo hacen en aplicaciones web o en las clásicas de escritorio. Esto es un enorme error de cara a la experiencia de usuario ya que provoca múltiples problemas derivados de los que enumero algunos a continuación:

  • El usuario cree que la aplicación se ha colgado y la cierra con la consiguiente mala reputación que nos ganaremos.
  • El usuario cree que la acción que ha realizado no se está ejecutando y vuelve a intentar realizarla. Si es una consulta no será tan drástica salvo que se volverá a generar el tráfico de red que corresponda pero, ¿si es una actualización o una creación de un registro? Puede que no hayamos controlado que el usuario le pueda dar varias veces y que nos genere datos erróneos, errores, … con la consiguiente insatisfacción por el usuario que se traduce en mala reputación.
  • Las Apps DEBEN ser fluidas y de respuesta inmediata. Recordemos que estamos desarrollando Apps y que el usuario espera que las acciones se ejecuten instantáneamente, es decir, no admite tener que esperar como hacía antiguamente en un PC 386 donde tener que esperar unos segundos era la tónica general y por tanto se aceptaba. Además, debemos recordar que puede que sea un usuario de un dispositivo de gama alta donde tiene la idea de que todo debe ser “ipso facto”.
  • Por simple buena experiencia de usuario UX. El usuario debe saber en todo momento qué ocurre con la aplicación en su dispositivo y esto no es negociable aunque el mensaje sólo aparezca, si todo va bien, unos milisegundos.
  • Algunos casos más que no he considerado necesarios nombrar.

¿Cómo lo implementamos?

Hay mil y una formas de implementar un aviso de carga, con CSS, JavaScript, GiF, … pero os voy a dejar unas directrices que sirven en cualquier caso y que yo sigo por buenas prácticas basadas en mi experiencia:

  • Debe ser claro y conciso, nada de mensajes como: “Estamos cargando los datos de la tabla de super héroes, calculando los índices, parseando el JSON y redimensionando las imágenes. Espere unos instantes, disculpe las molestias”. Un usuario no necesita saber tanto y, de hecho, probablemente nadie se lea tanto detalle. El usuario generalmente desea saber únicamente que se están cargando datos y, en caso de necesitar algo más de información podemos añadir algunas palabras pero sin pasarnos como “Cargando datos de superhéroes”.
  • Se puede dar el caso en el que la carga requiera de varios procesos, en ese caso, intercambiaremos unos mensajes por otros en función del estado del proceso como por ejemplo, “Cargando datos”, “Calculándo índices”, “Redimensionando imágenes”, de forma que el usuario sólo verá en pantalla el mensaje concreto y, si el proceso se detuviera un instante en alguno de los subprocesos, siempre sabría qué es lo que está ralentizando la carga.
  • Se DEBEN bloquear los elementos que generen la misma acción u otras que entren en conflicto. Lo más sencillo es bloquear la pantalla por completo con una capa que impida al usuario ejecutar cualquier acción. Puede darse el caso que por ejemplo, mientras se esté buscando queramos permitir al usuario ejecutar otras acciones en pantalla y, en este caso, sólo deberíamos mantener activos aquellos elementos que queramos que puedan ser accionados en ese caso. Si es una simple carga de datos incluso puede que no necesitemos bloquear ninguna acción, pero estudiad entonces muy bien esos casos “for if the flies”.
  • Se debe ver claramente salvo que no queramos bloquear la pantalla como en el caso anterior. Por ejemplo, en cargas en background podemos permitirnos el lujo de usar algo muy sutil como los puntitos que aparecen y desaparecen en Windows Phone.

Con estas directrices, que podéis saltaros, ignorar, completar, reducir,… ya estamos listos para pensar cómo queremos que sea nuestro aviso de carga. A mi en concreto me gusta ser un poco original y no limitarme a las típicas rueditas girando acompañadas con el mensaje “Cargando…” así que os compartiré mi idea para mi aplicación de Super Héroes realizada con Cordova.

Como se puede observar he puesto un mensaje claro de carga que habla un poco de la aplicación usando para ello una posible situación de ciencia ficción, además de añadir la silueta de un superhéroe volando por la pantalla. Está claro que se podría hacer más atractivo pero esto no es más que un ejemplo. Ahora veamos cómo lo he realizado.

Para hacer la animación simplemente he usado las características que nos proporciona CSS3 y he puesto un desplazamiento de derecha a izquierda ascendente como podéis ver en el siguiente código y que os explico ahora para ahorraros verlo.

  1. Añado un bloque oculto que contiene el texto y una imagen que será la que se mueva por la pantalla
  2. Les establezco posición absoluta y que el contenedor ocupe toda la pantalla con fondo negro translúcido
  3. Añado la animación mediante CSS de tal forma que vaya de derecha a izquierda en forma ascendente y que se repita infinitamente
  4. En el código JavaScript, muestro el bloque con el mensaje de carga de datos cuando se esté realizando la carga y lo oculto cuando se haya acabado.
  5. Las funciones JavaScript que he creado nos permiten indicar si se ha de mostrar o no, además del elemento que mostramos/ocultamos.

HTML

<div class="loading" style="display:none;">

    <div class="loading-text">Un momento, estamos salvando la galaxia</div>

    <img class="loading-img" src="images/layout/superhero-flying.png" />

</div>

 

CSS

body {

    margin: 0;

    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

}

 

.loading {

    position: absolute;

    top: 0;

    left: 0;

    height: 100%;

    width: 100%;

    background: rgba(0, 0, 0, 0.75);

    overflow: hidden;

}

 

    .loading .loading-text {

        position: relative;

        top: 50%;

        width: 100%;

        text-align: center;

        color: #ffde00;

        font-size: 17px;

    }

 

    .loading .loading-img {

        position: absolute;

        -moz-animation: loading 3s infinite;

        -o-animation: loading 3s infinite;

        -webkit-animation: loading 3s infinite;

        animation: loading 3s infinite;

    }

 

@-moz-keyframes loading {

    from {

        top: 60%;

        left: -60px;

    }

 

    to {

        top: 40%;

        left: 110%;

    }

}

 

@-webkit-keyframes loading {

    from {

        top: 60%;

        left: -60px;

    }

 

    to {

        top: 40%;

        left: 110%;

    }

}

 

@keyframes loading {

    from {

        top: 60%;

        left: -60px;

    }

 

    to {

        top: 40%;

        left: 110%;

    }

}

 

JavaScript

function onDeviceReady() {

    // Handle the Cordova pause and resume events

    document.addEventListener('pause', onPause.bind(this), false);

    document.addEventListener('resume', onResume.bind(this), false);

 

    // TODO: Cordova has been loaded. Perform any initialization that requires Cordova here.

    //checkConnection();

    loading(true);

 

    amscontext = new WindowsAzure.MobileServiceClient(

            "URL_SERVICIO_MÓVIL",

            "APPLICATION_KEY");

 

    getSuperHeros();

};

 

function getSuperHeros() {

    var superHeroTable = amscontext.getTable('superhero');

 

    superHeroTable.read().then(function (items) {

        displaySuperHeros(items);

        loading(false);

    });

}

 

...

...

...

 

function loading(visible, loadingSelector) {

    var selector = '.loading';

    if (loadingSelector != undefined)

        selector = loadingSelector;

 

    if (selector.indexOf('#') == 0) {

        var loadingElement = document.getElementById(selector.substring(1));

        DisplayElement(loadingElement, visible);

    }

    else if (selector.indexOf('.') == 0) {

        var loadingElements = document.getElementsByClassName(selector.substring(1));

        for (var i = 0; i < loadingElements.length; i++) {

            var loadingElement = loadingElements[i];

            DisplayElement(loadingElement, visible);

        }

    }

}

 

function DisplayElement(element, visible) {

    if (visible)

        element.style.display = 'block';

    else

        element.style.display = 'none';

}

 

 

 

Have fun & enjoy coding!!

Apache Cordova | Añadir logo a nuestra App

Square150x150Logo.scale-240 Algo muy importante de una App es el logo, ¿por qué? Porque es algo que debe diferenciar nuestra aplicación del resto entre una maraña de logos en la pantalla de inicio de nuestro dispositivo o peor aún, entre la mayor maraña aún de aplicaciónes instaladas. Es por eso que debemos usar un logotipo que cumpla estos criterios a ser posible (salvo excepciones):

  • Simple: Fácilmente identificable y recordable.
  • Relacionado con la aplicación: Debe indicar de qué tipo de aplicación se trata
  • Original: No copiéis logos de otras aplicaciones

Una vez hayamos seleccionado el logotipo, toca crear todos los formatos para las plataformas para las que estamos desarrollando nuestra aplicación por lo que es muy importante que hayamos creado nuestro logo de forma vectorial para que no pierda calidad en cada una de las resoluciones y, como son tantas, puede ser muy útil guiarse por los que se han creado con la plantilla del proyecto y que se encuentran en la carpeta /res/icons/PLATAFORMA tal y como se muestra en la imagen a continuación.

logos-folder

Una vez creados los logotipos, sólo nos queda indicar a la plataforma que los use tal y como se indica en la documentación de Cordova aunque, si no tocamos nada… ¡Magia! El sistema directamente reconoce los logotipos de las rutas por defecto y hace su trabajo 🙂

 

windows-phone-logoandroid-logo 

Espero que os sirva.

Have fun & enjoy coding!

HTML + JavaScript | Mostrar preview de imagen o cómo mostrarlas en base64

Estos días he tenido la necesidad de trabajar con un formulario de subida de imágenes y he tenido que montar una zona para mostrar la preview de las imágenes antes de subirlas al servidor para que el usuario pueda comprobar si todo es correcto antes de completar la operación. Hace algún tiempo (algunos años) creo recordar que vi alguna respuesta del gran Pedro Hurtado en los foros de MSDN acerca de esta cuestión pero no he podido encontrar dónde lo vi. Así que lo posteo para intentar ayudar a quien se encuentre en este caso y no sepa cómo alcanzar la solución.

Bien, como os iba contando, necesitamos que antes de subir las imágenes al servidor, el usuario pueda ver qué es lo que va a subir. Entre otras muchas soluciones, creo que una de las más adecuadas es usar la cadena en base64 que forma la imagen. ¿Qué? ¿Aún no sabías que se podía hacer? Es probablemente lo que oirías de muchas personas que tienen mucha experiencia, pero como no nacemos con un manual sobre desarrollo web en la cabeza, algún día tendréis que aprender al igual que yo lo aprendí del mencionado foro con la respuesta de Pedro, así que vamos a ver cómo se muestra una imagen:

  • Desde una url pública –> <img src=”http://DOMINIO/IMAGEN.XXX” />
  • Desde una url absoluta del proyecto –> <img src=”/DIRECTORIO/IMAGEN.XXX” />
  • Desde una url relativa del proyecto –> <img src=”../DIRECTORIO/IMAGEN.XXX” />
  • Usando base64 –> <img src=»data:image/jpeg;base64{binary data}» />

Hasta aquí todo perfecto y fácil de entender. Esto se ha usado por ejemplo cuando se guardaban imágenes en un campo de una tabla en la base de datos y se querían mostrar en pantalla. Pero bien, ahora ¿cómo lo aprovecho para hacerlo desde el navegador del usuario para poder mostrar una preview de una imagen? Bueno, para esto entre otras tantas soluciones, podremos aprovechar las capacidades con JavaScript de nuestros navegadores modernos (espero que los tengáis actualizados y no me valen excusas), así que vamos a usar la api de ficheros (File) y en concreto vamos a trabajar con FileReader.

Ejemplo:

HTML

<div id="divInputLoad">

    <h1>Test it uploading your own image</h1>

    <div id="divFileUpload">

        <input id="file-upload" type="file" accept="image/*" />

    </div>

    <div id="file-preview-zone">

    </div>

</div>

 

JavaScript

<script>

    function readFile(input) {

        if (input.files && input.files[0]) {

            var reader = new FileReader();

 

            reader.onload = function (e) {

                var filePreview = document.createElement('img');

                filePreview.id = 'file-preview';

                //e.target.result contents the base64 data from the image uploaded

                filePreview.src = e.target.result;

                console.log(e.target.result);

 

                var previewZone = document.getElementById('file-preview-zone');

                previewZone.appendChild(filePreview);

            }

 

            reader.readAsDataURL(input.files[0]);

        }

    }

 

    var fileUpload = document.getElementById('file-upload');

    fileUpload.onchange = function (e) {

        readFile(e.srcElement);

    }

 

</script>

 

Como podéis observar, lo que hago es conectarme al evento “onchange” del control de selección de ficheros (al que he puesto que sólo por defecto busque imágenes) y, en cuanto reciba un cambio, se ejecuta la función readFile que recoge como parámetro el control. Se comprueba si tiene un fichero y, en caso de tenerlo (el ejemplo es para un único fichero), se crea una nueva instancia de FileReader y ejecuta la función “readAsDataURL” que leerá el fichero desde la ruta en disco.

Una vez leído el fichero, se ejecutará la función suscrita al evento “onload” de la instancia de FileReader. Entonces, se crea el DOM del elemento img donde se va a mostrar la preview y se le asigna como source “src” el resultado de la lectura del fichero que, por supuesto, está en base64. E voilà! Ya tenemos la preview de la imagen sin haberla subido al servidor.

image

Aquí tienes el código de ejemplo

download-code

Apache Cordova | Conectar una aplicación con Azure Mobile Services

posterDespués de empezar una aplicación con Apache Cordova en un artículo anterior, no sin bastantes problemas con los emuladores, habrá que darle algo de funcionalidad a esa aplicación para poder decir que sirver para algo. En este caso, lo que quiero hacer es obtener una lista de elementos de un servicio Azure Mobile Services que tengo creado para otras demos, y no es otro que mi servicio de Superhéroes (geek mode on). Así que si no habéis creado aún vuestro servicio, podéis empezar por ese paso antes de continuar con la aplicación.

Tened en cuenta que, aunque debería funcionar la forma de usarlo Azure Mobile Services que está especificada en la página de MSDN referente a Azure Mobile Services desde HTML, al menos en mi caso ha sido un problema ya que no me ha funcionado y he tenido que depurar durante un buen rato junto al gran maestre de Windows Platform Josue Yeray. ¿Por qué? Pues básicamente el plugin devuelve los datos ya formateados en objetos y no en Json.

 

Crear el servicio Azure Mobile Services

No me detendré en explicar esta parte porque creo que está más que repasada, en millones de artículos, es muy muy sencillo y siguiendo la documentación de MSDN no se tarda más de 1 minuto. Así que una vez tengáis el servicio Azure Mobile Service, ya sólo necesitáis enlazarlo con la aplicación realizada con Apache Cordova. Manos a la obra.

Configurar el servicio

Voy a hacer un pequeño inciso porque es necesario que sepamos que debemos configurar el servicio para que admita CORS (Cross-Origin Resource Sharing). ¿Que por qué? Pues es sencillo, tengamos que cuenta que estamos desarrollando con HTML+JavaScript+CSS, y que el emulador Ripple por ejemplo se ejecuta en un navegador, así que será un acceso al servicio desde un supuesto website. Esto quiere decir, que se regirá por las reglas de acceso desde un sitio web a nuestro servicio móvil en Azure.

  1. Vamos al portal de Azure (voy a hacerlo desde el portal antiguo)
  2. Seleccionar Azure Mobile Services
  3. Seleccionar el servicio
  4. Del menú, escoger la opción “Configurar”
  5. Buscar la sección “uso compartido de recursos entre orígenes (cors)
  6. En los orígenes permitidos, poner la URL de un sitio web desde el que vayamos a acceder, o de la url desde la que estemos depurando (http://localhost:XXXX), o, si queremos arriesgarnos, podemos permitir cualquier lugar de acceso poniendo “*”

azure-mobile-service

 

Instalación del plugin de Azure Mobile Services

El primer paso que debemos dar es instalar el plugin de Azure Mobile Services, para ello abrimos el archivo config.xml (si se nos abre en XML, seleccionarlo con el botón derecho del ratón y escoger “Ver diseñador” o “View designer”). Una vez se nos abra el diseñador del archivo de configuración, vamos a la pestaña “Plugins” como se puede apreciar en la imagen y seleccionamos el plugin Windows Azure Mobile Services que como podemos comprobar nos habilita su uso en iOS, Android y plataforma Windows.

select-plugin

Ahora instalamos el plugin seleccionando el botón “Add” y automáticamente se añadirá la carpeta correspondiente en “plugins” como se puede ver en la imagen.

plugin-installed

 

Obtener datos de Azure Mobile Services y mostrarlos en pantalla

Ya tenemos el plugin en nuestra aplicación, así que ya podemos hacer uso de él. Para ello, vamos al fichero “index.js” y comenzamos a hacer la “magia”.

Yo me creado una función, getSuperHeros que me devolverá los héroes de la base de datos, y otra función “displaySuperHeros” que será la encargada de generar el DOM a partir de los elementos devueltos y los muestra en pantalla. Veamos el código.

HTML “index.html”

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <title>SuperHero.Cordova</title>

 

    <!-- SuperHero.Cordova references -->

    <link href="css/index.css" rel="stylesheet" />

</head>

<body>

    <section id="sectionMain">

        <header><h1>SuperHero App</h1></header>

        <section id="listSuperHeros">

        </section>

    </section>

 

    <!-- Cordova reference, this is added to your app when it's built. -->

    <script src="cordova.js"></script>

    <script src="scripts/platformOverrides.js"></script>

 

    <script src="scripts/index.js"></script>

 

</body>

</html>

JavaScript “scripts/index.js”

...

...

 

var amscontext;

 

function onDeviceReady() {

    // Handle the Cordova pause and resume events

    document.addEventListener('pause', onPause.bind(this), false);

    document.addEventListener('resume', onResume.bind(this), false);

 

    // TODO: Cordova has been loaded. Perform any initialization that requires Cordova here.

    //checkConnection();

 

    amscontext = new WindowsAzure.MobileServiceClient(

            "https://NOMBRE-DEL-SERVICIO.azure-mobile.net/",

            "CLAVE-DE-APLICACIÓN-DEL-SERVICIO");

 

    getSuperHeros();

};

 

...

...

 

function getSuperHeros() {

    var superHeroTable = amscontext.getTable('superhero');

 

    superHeroTable.read().then(function (items) {

        displaySuperHeros(items);

    });

}

 

function displaySuperHeros(superHeros) {

    var superHerosContainer = document.getElementById('listSuperHeros');

    for (var i = 0; i < superHeros.length; i++) {

        var superHero = superHeros[i];

 

        var article = document.createElement('article');

        var picture = document.createElement('div');

        picture.setAttribute('class', 'hero-picture');

        picture.style.background = 'url(' + superHero.picture + ') no-repeat';

        picture.style.backgroundPosition = 'center';

        picture.style.backgroundSize = 'cover';

        article.appendChild(picture);

 

        var header = document.createElement('header');

        var title = document.createElement('h2');

        title.innerText = superHero.title;

        header.appendChild(title);

        article.appendChild(header);

 

        superHerosContainer.appendChild(article);

    }

    var a = 1;

}

Estilos “css/index.css”

body {

    background: #32004b;

    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

    color: #fff;

}

 

    body > section#sectionMain > header > h1 {

        font-size: 27pt;

        font-weight: 100;

        color: #ffde00;

    }

 

    #listSuperHeros > article {

        display: inline-block;

        margin: 5px 1%;

        box-sizing: border-box;

        width: 48%;

        height: 150px;

        vertical-align: top;

    }

 

        #listSuperHeros > article .hero-picture {

            width: 100%;

            height: 120px;

        }

 

        #listSuperHeros > article header h2 {

            height: 30px;

            line-height: 30px;

            white-space: nowrap;

            overflow: hidden;

            margin: 0;

            font-size: 15pt;

            font-weight: 300;

            color: #ffde00;

        }

 

Una vez tengamos todo listo, ejecutamos la aplicación y… atentos que aquí tenemos que poner una “Nota al margen”, tenemos que configurar Ripple para que haga uso del “CORS” que establece el servicio. Para ello, expandimos la sección “settings” que se encuentra en el lado derecho del navegador con Ripple y, en “Cross Domain Proxy” hay que seleccionar “Remote” tal y como se muestra en la imagen. ¡¡Hecho!! Ahora ya vemos los datos en el simulador.

ripple-result

Otro apunte más, si ejecutamos la aplicación en el emulador “nativo” de una plataforma o en nuestros dispositivos, no tendremos el problema de tener que configurar el proxi para el Cross Domain puesto que no sólo es necesario en el navegador.

Have fun & enjoy coding!!

Windows 10 | Cómo actualizar a la última versión hoy mismo

windows_10_0 Ya ha sido presentado Windows 10 con grandes novedades tanto para usuarios estándar como para empresas y la verdad es que me parece una auténtica pasada lo que se han currado en Redmond en todos los aspectos y todo lo que viene alrededor de esta nueva versión del Sistema Operativo más popular.

Ahora bien, a los que ya nos habíamos subido al carro de Windows 10 instalando la preview para poder probarlo y enviar feedback a Microsoft, nos apuraba la posibilidad de tener una actualización de dicha preview ya que hacía bastantes semanas que no veíamos ningún cambio. En la presentación, se anunció que en unos días comenzaría a llegar la actualización pero al menos en mi sistema aún no pasaba nada. Pero la clave me la dio Alberto Díaz y no es más que seguir estos pasos:

  1. Ir a la pantalla de actualizaciónes de Windows en Configuración –> Actualización y recuperación o Settings –> Update & recovery para los que lo tengamos en inglés.
  2. Seleccionar la opción del panel de la izquierda que pone “Preview updates”.
  3. Seleccionar la opción “comprobar actualizaciones” o “check updates”.

E voilà, nos aparecerá que hay una nueva actualización.

 

cortana

Una vez se descargue, le damos a instalar y tras varios reinicios tendremos por fin la ansiada actualización de Windows 10 con la versión 9926 (al menos en Enterprise).

Novedades que he apreciado a simple vista:

  • Integración con Cortana
  • Rediseño de la barra de las ventanas
  • Rediseño de los iconos de escritorio
  • Rediseño de los iconos de la barra de tareas que cuando tenemos una aplicación abierta nos pone una barrita en la parte izquierda
  • Ya vuelve a funcionar compartir escritorio con Lync
  • Cambios sutiles en el menú de inicio

image

Lamentablemente ahora hay algunas cosas que no funcionan como cabe de esperar en una preview y, por ejemplo, no podremos buscar aplicaciones directamente escribiendo tras abrir el menú de inicio, cosa que supongo que se resolverá en próximas actualizaciones 🙂 Tampoco funciona Cortana con la región que tengo especificada, así que tendré que esperar para ver todo lo que nos ofrece.

 

Enjoy Windows 10!

Fantasmas del código | ¿Problemas con Metro UI CSS 2.0 en un sitio ASP.NET MVC al publicar en Azure?

posterAunque no soy muy amigo de los elemento de ayuda a nuestros estilos porque a veces nos causan más problemas que beneficios y, sobre todo porque muchas veces podemos hacerlo mejor por nuestra cuenta, estos días he estado probando Metro UI CSS 2.0 en una aplicación web que va a ser alojada en Azure Web Sites y la verdad es que es un “plugin” muy bueno si queremos que nuestras aplicaciones tengan un look&feel con los estilos Modern UI de Microsoft.

Metro UI CSS 2.0 dispone de una gran cantidad de estilos que pueden convertir nuestro sitio en algo realmente atractivo, diferente y moderno. Entre otras muchas cosas, podemos tener lo siguiente:

  • Controles básicos: Botones, Títulos, Input, Textarea,…
  • Menús de navegación
  • Caminos de hormigas (breadcrumbs)
  • Controles avanzados: Slider, Switch, Carrusel, Listas, TreeViews, …
  • Tiles
  • Wizards
  • Calendarios y controles de fecha
  • Más controles avanzados como Rating, Progress Bar, Scroll Bar,…
  • Tablas con Datatable
  • Y mucho más

Todo ello seguro que le servirá a más de uno para construir sitios muy buenos y ganarse el “respeto” de sus clientes y, si ya sabemos hacer algunas personalizaciones, podremos construir aplicaciones complejas con un Branding adecuado para cada cliente y que nos hagan valer nuestro peso en oro. Muy muy recomendable, así que para sus creadores, mis más sinceros respetos 😛

respect

Problema

Después de la entrada que parecía publicitaria, entremos en materia y pasemos a la acción. Metro UI CSS 2.0 usa una fuente “icónica” para representar los iconos que usa en algunos de sus elementos como por ejemplo el botón de configuración con esa rueda dentada o engranaje que seguro que muchos de vosotros usaréis en vuestros sitios web. En concreto, hablaré del menú que propone este “plugin” y que como podréis observar dispone del botón de configuración en su parte derecha.

menú

Si hacemos las cosas como Microsoft nos propone, agregaremos los estilos de este plugin usando el fichero BundleConfig y creando ese “conjunto” de estilos con su alias para poder integrarlo en nuestras páginas HTML.

bundles.Add(new StyleBundle("~/Content/vendor/metroui").Include(

          "~/Content/vendor/metroui/css/metro-bootstrap.min.css",

          "~/Content/vendor/metroui/css/metro-bootstrap-responsive.min.css",

          "~/Content/vendor/metroui/css/iconFont.min.css"));

 

Ahora  implementamos el menú tal y como se nos indica en la página y lo probamos en local, voilà, todo perfecto y tendremos nuestro bonito menú Modern UI funcionando de forma perfecta, así que procedemos a publicar en Azure nuestro sitio y WTF! en Microsoft Azure no se ven los iconos de Metro UI CSS 2.0 basados en la fuente “icónica”.

Es en este momento en el que me pongo a indagar el problema y una solución al mismo y tras mucho googlear y ver posibles soluciones como cambiar el alias del “Bundle” para que no sea el prefijo de la ruta (que no me funcionó), decidí abrir el fiddler y ver qué ocurría con las peticiones que hacía el sitio web y… aquí el problema, recibimos el error 103 por algún motivo (que aún no alcanzo a entender)

fiddler 

Solución

Como ya os comenté, hay muchas personas que hablan de cambiar el alias al Bundle pero eso no funciona o al menos no funcionó en mi caso, así que busqué un poco mejor y entre artículo y artículo, se me ocurrió que hubiera algún problema entre la compresión que realiza el Bundle a la hora de y la ruta de los archivos de las fuentes dentro de las hojas de estilo (por pensar cosas absurdas), así que decidí pasar del Bundle y poner de forma explícita la instancia a las hojas de estilo de Metro UI CSS 2.0.

@Styles.Render("~/Content/vendor/metroui/css/metro-bootstrap.css")

@Styles.Render("~/Content/vendor/metroui/css/metro-bootstrap-responsive.css")

@Styles.Render("~/Content/vendor/metroui/css/iconFont.min.css")

Nuevamente probamos la publicación del sitio y… ¡Perfecto! Problema solucionado (aunque no sea de la mejor forma)

 

Enjoy coding!

Apache Cordova | Primeros pasos con mi primera App Multiplataforma

poster Desde hace ya algún tiempo Microsoft ha acogido Apache Cordova entre las tecnologías con las que podemos desarrollar en Visual Studio. Esto nos permitirá hacer uso del mejor IDE de nuestros días para poder desarrollar aplicaciones multiplataforma con HTML y JavaScript sin muchos los dolores de cabeza que nos puede generar tener que usar varios IDEs diferentes y poder conseguir desarrollar nuestras aplicaciones para todas las plataformas que deseemos de una forma muy fácil.

Preparando el entorno de desarrollo

Para empezar, lo primero que debemos tener es Visual Studio en sus versiones 2013 o 2015, preferiblemente este último ya que nos facilita mucho las cosas como veremos más adelante. El siguiente paso, será instalar Visual Studio Tools for Apache Cordova, que nos permitirá disponer de herramientas que agilizarán los desarrollos, así como una amplia gama de emuladores.

Una vez ya tengamos preparado el sistema, podemos comenzar a desarrollar nuestra aplicación.

Creando el proyecto

Comenzamos creando el proyecto desde las plantillas que nos proporcionará Visual Studio gracias a las herramientas que le hemos instalado. Para ello, seleccionamos JavaScript como lenguaje y ya podremos acceder a la plantilla de aplicación en blanco para Apache Cordova.

cordova-project-template

 

Una vez establecido el nombre del proyecto, la localización donde lo crearemos y el nombre de la solución, presionamos OK y podremos ver la estructura que ha creado la plantilla.

cordova-project-structure

 

Como se puede apreciar, es una plantilla compleja que contiene personalizaciones para la diferentes plataformas que en este caso son iOS, Android, Windows Phone y Windows, lo que nos permitirá una gran facilidad de adaptar nuestras aplicaciones sea cual sea el caso. Es muy importante tener en cuenta los ficheros index.html e index.js.

Primera ejecución del proyecto

En este punto, la aplicación ya es funcional y podemos ejecutar el proyecto para cualquiera de las plataformas y en cualquiera de los emuladores provistos

cordova-targets

cordova-emulators

 

Por ejemplo, si seleccionamos Android y VS Emulator Android Phone obtendremos el siguiente resultado

cordova-android-emulator

 

Esto se corresponde con lo que se establece en el fichero index.html que viene por defecto en la plantilla

image

 

Añadiendo plugins

Una de las virtudes de usar Visual Studio 2015 es que nos facilitará esta tarea, gracias a que dispone de una interfaz visual para gestionar la configuración del proyecto. Así pues, si abrimos el archivo config.xml, nos aparecerá una ventana que nos permitirá controlar los aspectos de nuestra aplicación en lugar de tener que estar editando a mano el fichero xml con los consiguientes riesgos de equivocarnos o simplemente con el problema de no saber qué poner.

Lo que podemos realizar desde esta interfaz será gestionar información común de la aplicación, los plugins que vamos a usar y que vienen predefinidos y por último configuración específica de Windows, Android e iOS, pero centrémonos en los plugins. Aquí podemos encontrar una serie de plugins muy usados, como el que nos permite acceder a la cámara, que ya nos proveen del código necesario para poder trabajar en las diferentes plataformas, con lo que nos olvidaremos de tener que reescribir el código una y otra vez y aprovecharemos esta abstracción para sólo tener que escribir qué queremos hacer que el plugin ya se encarga de ejecutar el código específico de cada plataforma.

cordova-plugins

 

Como se puede apreciar en la imagen, al seleccionar un plugin se muestra información de las plataformas para las que está preparado y sólo necesitaremos instalarlo para poder hacer uso de él de una forma muy sencilla. Por ejemplo, voy a instalar el plugin Network Information

cordova-plugin-network

 

Una vez instalado, podremos ver que se ha añadido a la carpeta “plugins” y ya podremos comenzar a utilizarlo sin tener que hacer mucho más.

cordova-plugins-installed

 

Ahora sólo tenemos que abrir el fichero index.js y ya podremos empezar a escribir nuestro código. Valga como ejemplo la muestra que nos dan en la página de GitHug del plugin y que es el siguiente:

function checkConnection() {

    var networkState = navigator.connection.type;

 

    var states = {};

    states[Connection.UNKNOWN] = 'Unknown connection';

    states[Connection.ETHERNET] = 'Ethernet connection';

    states[Connection.WIFI] = 'WiFi connection';

    states[Connection.CELL_2G] = 'Cell 2G connection';

    states[Connection.CELL_3G] = 'Cell 3G connection';

    states[Connection.CELL_4G] = 'Cell 4G connection';

    states[Connection.CELL] = 'Cell generic connection';

    states[Connection.NONE] = 'No network connection';

 

    alert('Connection type: ' + states[networkState]);

}

 

checkConnection();

 

NOTA: Para mostrar el popup tendremos que instalar el plugin “Notification”.

 

Esto dejaría el fichero de esta forma

image 

Podemos ejecutar de nuevo la aplicación, en esta ocasión lo haré en Ripple para Nexus (Galaxy), en Ripple para iPhone y en el emulador de Windows Phone y veremos como resultado que nos sale un popup mostrando el estado de la conexión.

windows-phone

Windows Phone

 

ripple-android Ripple Android – Nexus (Galaxy)

ripple-iphone

Ripple iPhone

 

NOTA IMPORTANTE: Si al ejecutar tenemos problemas con que no puede abrir Ripple, o el emulador de Android porque no puede ejecutar el fichero adb.exe o incluso tampoco nos abre el emulador de Windows Phone, podemos probar una de estas soluciones:

Solución 1: Eliminar la caché de Cordova en Herramientas –> Opciones –> Tools for Apache Cordova y seleccionamos Clear Cordova Cache.

Solución 2: Ir a la carpeta del proyecto eliminar el fichero .suo , mostrar elementos ocultos y eliminar también el fichero .suo que se encuentra en .vsNOMBRE_PROYECTOv14

 

Espero que este artículo os anime a usar Apache Cordova y hagáis buenas aplicaciones CrossPlatform

 

Enjoy coding!

Pinta y colorea | Cuando el cliente quiere diseñar un sitio web o una aplicación

niños-pintando-arboles-navideños Esto es un artículo de “crítica” hacia aquellos clientes que creen ser diseñadores, aquellos que ven un color (o varios), un dibujo (o varios), una maquetación (o varias) y lo quiere todo en su site. Es muy común entre los que desarrollamos aplicaciones para clientes encontrarnos con que los mismos quieren “dirigir” cómo se diseña su página y, me parece bien que nos cuenten sus ideas generales pero no que las quieren imponer. Os preguntaréis “¿Por qué? ¿Pero si así me ahorro romperme los sesos pensando en una buena experiencia de usuario y en la usabilidad?” y diréis “pero si me está pagando y está haciendo él el trabajo”. Desde mi punto de vista es un error grave tanto por parte del cliente como por nuestra parte permitírselo y os explicaré por qué.

Conocimiento

Auto conocimientoGeneralmente (por no decir siempre) dichos clientes tienen los mismos conocimientos que yo de ingeniería aeroespacial, es decir, ninguno y se basan en cosas “bonitas” que han visto en algún lugar o cosas que ven en otros lugares y que les parecen que son “estándares”. Bajo mi experiencia y por lo que he podido estudiar, no hay “estándares” en cuanto a diseño, UX y maquetación se trata sino que tenemos unas reglas básicas que seguir y que muy pocas veces vemos en práctica en aplicaciones y sitios web bastante más comunes de lo que me gustaría. Por ejemplo, hay muchas tiendas online populares que han sacrificado la usabilidad y la experiencia de usuario para aumentar la funcionalidad en cada página y a menudo me encuentro en alguna de estas tiendas buscando algún elemento como “¿dónde están los artículos que he comprado (ebay)?”. Quizás la razón no sea ni siquiera esa, sino que más allá de querer tener más funcionalidad, dichos sitios nunca hayan pasado por la mano de alguien con algún criterio de diseño, experiencia de usuario, usabilidad,… Entonces, ¿por qué si sabemos que dichos sites hacen las cosas mal dejamos que el cliente nos obligue a copiarlo? ¿Acaso valoramos tan poco nuestro trabajo, nuestro criterio y por tanto a nosotros mismos?

Confianza

confianza.jpg_2033098437Los clientes, que son los que nos pagan, a menudo tienen un cambio de confianza en cuanto empezamos el proyecto, por un lado se toman mayor confianza y nos tratan como si fuéramos sus empleados exigiendo a veces cosas sin sentido y, por otro lado, en cuanto hemos empezado es como si perdieran la confianza en que nosotros somos los “expertos” en lo que nos han coontratado y dejan de guiarse por nuestro criterio tratando de imponer el suyo porque, claro… es el acertado y nosotros no sabemos de nuestro trabajo. Es como si lleváramos nuestros coche al taller y en cuanto el mecánico empieza a trabajar le decimos cómo lo tiene que arreglar… Si fuera así, creo que los desguaces estarían desbordados y sería el negocio en auge.

 

Calidad de trabajo

calidad¿Alguna vez habéis intentado pintar un cuadro? ¿Habéis visto a un pintor trabajar? ¿Notáis alguna diferencia? La diferencia es la calidad del trabajo (amén de que el pintor tarda menos si trabaja tranquilo) y será mucho más creativo. Como una imagen vale más que mil palabras… aquí va un ejemplo muy famoso y que plasma muy bien la diferencia entre un profesional y un “algo”, así que aquí tenéis el Cristo de Borja que una señora sin más conocimientos de pintura que los de una “aficionada” le hizo un “cristo” al Cristo…

 

cristo-de-borja

Conclusión

¿Qué tipo de profesional eres y cuál quieres ser? ¿Le das valor a tu nombre que es tu marca personal? ¿Quieres que te conozcan por chapuzas o por profesional? Al final el trabajo, sea con tu diseño o sea con el que te diga el cliente, llevará tu nombre y eso te dará valor o te lo restará. Con esta premisa, desde un primer momento debemos dejar claro a nuestro clientes que nosotros somos los profesionales, que sus ideas aportan valor en cuanto nos permiten conocer qué espera de la aplicación pero como norma general, esas mismas ideas no serán plasmadas como originalmente las pensó sino que se estudiará la forma de que la funcionalidad sea la que quiera el cliente con un diseño acorde a lo que realmente necesita y, sobre todo, que no se debe atar a lo que ha visto, si no, aún iríamos con una hoja para tapar nuestras zonas íntimas…

Así que, “Cliente, deja diseñar al diseñador y deja programar al desarrollador que para eso le has pagado un caché”.