Este PRD (Product Requirements Document) describe JSWidgets, una aplicación Android inspirada en Scriptable. El documento cubre:
- Visión del producto
- Objetivos
- Estado Actual del Proyecto
- Inspiración: Adaptando la Experiencia Scriptable a Android
- Características clave
- Arquitectura funcional
- Casos de uso
- Requisitos técnicos
- Fases del desarrollo
- Consideraciones futuras (General)
- User Flow (Flujo de Usuario Actualizado)
Crear una aplicación para Android que permita importar y ejecutar scripts en JavaScript para generar contenido dinámico y personalizable en widgets, inspirado en la experiencia que ofrece Scriptable en iOS. Esta herramienta busca empoderar a usuarios técnicos con una forma flexible de convertir código en widgets funcionales directamente desde su Android.
- Permitir a los usuarios crear widgets visuales y personalizables basados en lógica propia escrita en JavaScript.
- Ofrecer una sandbox de ejecución de JavaScript (actualmente con Rhino) con acceso controlado a APIs de Android y Java para funcionalidades extendidas (ej. peticiones de red).
- Facilitar la gestión, creación y edición de scripts directamente en la aplicación, además de permitir la importación de archivos
.jsdesde el almacenamiento del dispositivo. - Proporcionar una experiencia de usuario fluida para la configuración y visualización de widgets en el homescreen.
- (Futuro) Ofrecer un preview de ejecución en tiempo real dentro del editor para acelerar el ciclo de edición-prueba.
- Interfaz de Usuario Principal:
- Pantalla principal con listado de scripts de usuario y ejemplos.
- Diseño de items de script con colores cíclicos, icono personalizable (seleccionable por el usuario) y menú de acciones (Editar, Renombrar, Borrar).
- Diálogos de confirmación para borrado y renombrado.
- Editor de scripts integrado con resaltado de sintaxis (monoespaciado) y selector de iconos.
- Funcionalidad de búsqueda de scripts (placeholder).
- Gestión de Scripts:
- Creación, edición, renombrado y borrado de scripts.
- Los scripts de usuario se guardan en el almacenamiento externo.
- Carga automática de scripts de ejemplo desde los
assetsde la aplicación si no hay scripts de usuario.
- Motor de JavaScript:
- Uso de Mozilla Rhino para ejecutar scripts.
ContextFactorypersonalizado que permite a los scripts acceder a clases Java específicas (ej.java.net.URL,org.json.JSONObject) medianteapplicationClassLoader.
- Widgets:
- Proveedor de widgets (
JSWidgetProvider) que ejecuta el script seleccionado. - Actividad de configuración (
WidgetConfigActivity) que permite al usuario elegir qué script asociar a una instancia de widget. - Los scripts retornan un objeto JSON con propiedades para personalizar el widget, incluyendo:
title(String, opcional)body(String, contenido principal)backgroundColor(String, color hexadecimal ej. "#FFFFFF", opcional)textColor(String, color hexadecimal, opcional)textSize(Number, tamaño de fuente en sp, opcional)textAlign(String, "left", "center", "right", opcional)refreshInterval(Number, minutos, opcional, mínimo 15)
- Manejo básico de errores en widgets (muestra "Contenido no disponible" o "Script no encontrado").
- Actualización periódica de widgets.
- Proveedor de widgets (
- Permisos:
READ_EXTERNAL_STORAGEpara cargar scripts de usuario.INTERNETpara scripts que necesiten acceso a la red (ej. widget de precio de BTC).WRITE_EXTERNAL_STORAGE(conmaxSdkVersion="28") para guardar scripts de usuario.
JSWidgets se inspira en la flexibilidad y potencia de Scriptable en iOS, buscando ofrecer una experiencia comparable adaptada al ecosistema Android:
- Scripts en JavaScript Puro (ES6 Soportado): Al igual que Scriptable, JSWidgets utiliza archivos JavaScript (
.js) estándar. El motor Rhino actual ofrece una amplia compatibilidad con ES6, permitiendo código moderno y legible. Los scripts se almacenan directamente en el sistema de archivos del dispositivo. - Integración con APIs Nativas de Android/Java: Inspirado en el acceso nativo de Scriptable, JSWidgets busca ofrecer una integración controlada y segura con las APIs de Android y Java. Actualmente, esto permite a los scripts realizar operaciones como peticiones de red (
java.net.URL) y manipulación de JSON (org.json.JSONObject). El objetivo es expandir estas capacidades para interactuar con más aspectos del sistema (sensores, archivos, calendario, etc.) de forma segura. - Automatización y Widgets Dinámicos (Equivalente Android a Atajos de Siri): Mientras Scriptable se integra con Atajos de Siri, JSWidgets se enfoca en la creación de widgets de homescreen altamente personalizables. A futuro, se explorará la integración con herramientas de automatización de Android (ej. Tasker), App Shortcuts (atajos de aplicación) y Quick Settings Tiles (controles en panel de ajustes rápidos) para ejecutar scripts y presentar información de formas diversas y rápidas.
- Documentación Clara y Accesible: Un pilar de Scriptable es su documentación. JSWidgets aspira a proveer documentación detallada y accesible (idealmente offline) para todas las APIs nativas expuestas a JavaScript, facilitando la creación de scripts complejos.
- Procesamiento de Datos desde Otras Apps (Equivalente Android a Share Sheet Extension): (Futuro) Al igual que Scriptable puede procesar entradas desde la Share Sheet, se planea permitir que JSWidgets reciba datos de otras aplicaciones a través del sistema de "Compartir" de Android, permitiendo a los scripts actuar sobre texto, URLs, etc.
- Integración con el Sistema de Archivos: JSWidgets ya interactúa con el sistema de archivos para cargar y guardar scripts. Se contempla expandir las APIs para permitir a los scripts realizar operaciones de archivo más avanzadas directamente desde los mismos, similar a la integración de Files.app en Scriptable.
- Editor Personalizable y Ejemplos: JSWidgets incluye un editor de scripts y scripts de ejemplo para un inicio rápido. A futuro, se buscará que el editor sea más personalizable (temas, fuentes), siguiendo la línea de Scriptable.
- Comunicación Inter-App (Intents de Android): En Android, los Intents son el mecanismo principal para la comunicación entre apps. (Futuro) JSWidgets podría usar Intents para permitir que los scripts inicien acciones en otras apps o para que JSWidgets sea invocado y controlado por otras aplicaciones, de forma análoga a cómo Scriptable utiliza x-callback-url.
- Carga scripts
.jsdesde el almacenamiento externo del dispositivo (directorio específico de la app y directorio públicoDocuments/JSWidgets). - Carga scripts de ejemplo empaquetados en los
assets. - Interfaz para listar, crear, editar (incluyendo icono), renombrar y eliminar scripts.
- Icono personalizable para cada script, visible en las listas y el editor.
- Ejecuta scripts usando Mozilla Rhino.
- Contexto de ejecución configurado para permitir el uso de ciertas clases Java (ej.
java.net.URL,org.json.JSONObject) para funcionalidades como peticiones HTTP y parseo de JSON. - Los scripts son autocontenidos (no se soportan módulos
require()al estilo Node.js).
- Cada instancia de widget en el homescreen está vinculada a un script JS específico seleccionado por el usuario.
- El script retorna un objeto JSON cuyas propiedades definen el contenido y apariencia del widget. Ejemplo de estructura retornada:
return {
title: "Bitcoin Price",
body: "USD " + btcPrice,
backgroundColor: "#263238",
textColor: "#FFFFFF",
textSize: 18,
textAlign: "center",
refreshInterval: 30 // minutos
};- El widget renderiza el contenido (título y cuerpo) basándose en las propiedades devueltas por el script.
- Soporta personalización básica de:
- Color de fondo del widget.
- Color del texto.
- Tamaño del texto.
- Alineación del texto.
- Diseño base con esquinas redondeadas.
- Los widgets se actualizan periódicamente según el
refreshIntervaldefinido en el script (mínimo 15 minutos debido a restricciones de Android). - Actualización al reconfigurar o añadir el widget.
- (Futuro) Posibilidad de actualización manual desde la app principal.
App (JSWidgets):
- Administra los scripts (CRUD).
- Proporciona un editor de texto para los scripts.
- Lanza la actividad de configuración de widgets.
- (Futuro) Previsualiza la ejecución del script.
Motor JS (Rhino integrado):
- Evalúa el código JavaScript del script seleccionado.
- Proporciona un entorno de ejecución con acceso limitado y controlado a funcionalidades del sistema/Java.
- Devuelve el objeto JSON resultante de la ejecución del script.
WidgetProvider (JSWidgetProvider):
- Asociado con las instancias de widgets en el homescreen.
- Recupera el script asociado a un widget (vía
SharedPreferencespobladas porWidgetConfigActivity). - Invoca al motor JS para ejecutar el script.
- Renderiza el widget (actualiza las
RemoteViews) con la información obtenida del script. - Maneja los ciclos de actualización del widget (
onUpdate,onDeleted). - Gestiona la persistencia de qué script está asociado a qué
appWidgetId.
Actividad de Configuración (WidgetConfigActivity):
- Se lanza cuando el usuario añade un nuevo widget al homescreen.
- Muestra la lista de scripts disponibles (de usuario y ejemplos).
- Permite al usuario seleccionar un script para la instancia del widget.
- Guarda la asociación script-widgetId y fuerza la primera actualización del widget.
- Crear un nuevo script:
- El usuario abre la app JSWidgets.
- Pulsa el botón "+" para crear un nuevo script.
- Ingresa un nombre para el script y escribe/pega el código JavaScript en el editor.
- Guarda el script.
- Añadir un widget al homescreen:
- El usuario añade un widget de JSWidgets desde el selector de widgets de Android.
- Se abre la
WidgetConfigActivitymostrando la lista de scripts. - El usuario selecciona el script deseado.
- El widget aparece en el homescreen mostrando el contenido generado por el script.
- Editar un script existente:
- El usuario abre la app y selecciona un script de la lista.
- Modifica el código en el editor y guarda los cambios.
- Los widgets que usan ese script se actualizarán con la nueva lógica en su próximo ciclo de actualización.
- Usar un script con acceso a internet (ej. precio de BTC):
- El usuario selecciona o crea un script que realiza una petición HTTP (ej. a CoinGecko).
- El script utiliza
java.net.URLpara la petición yorg.json.JSONObjectpara parsear la respuesta. - El widget muestra el precio de Bitcoin actualizado.
- (Futuro) El usuario descarga un script
.jsde una fuente externa, lo guarda en su dispositivo. La app (mediante una función de importación o detectándolo en una carpeta específica) lo añade a su lista de scripts disponibles.
- Lenguaje base: Kotlin.
- Motor JS: Mozilla Rhino.
- Compatibilidad mínima: Android 8.0+ (API nivel 26+).
- Permisos requeridos:
android.permission.INTERNET(para scripts que acceden a la red).android.permission.READ_EXTERNAL_STORAGE(para cargar scripts de usuario).android.permission.WRITE_EXTERNAL_STORAGE(conandroid:maxSdkVersion="28", para guardar scripts de usuario en versiones antiguas de Android; en versiones nuevas se usa el almacenamiento específico de la app que no requiere este permiso explícito de la misma manera).
- Restricciones y Consideraciones de Seguridad:
- Los scripts se ejecutan en un entorno con acceso limitado.
- Se debe tener cuidado con los scripts de fuentes no confiables.
- (Futuro) Implementar timeouts más estrictos para la ejecución de scripts para evitar bloqueos del widget o consumo excesivo de batería.
- Manejo de errores: los scripts con errores de sintaxis o excepciones durante la ejecución actualmente muestran un mensaje genérico en el widget ("Contenido no disponible"). Esto debe mejorarse para ofrecer feedback más específico.
- Ejecutar script JS desde archivo (assets y almacenamiento externo, incluyendo
Documents/JSWidgets). ✔️ - Retornar una estructura JSON con datos para el widget. ✔️
- Mostrar contenido y aplicar estilos básicos (texto, color de fondo/texto, tamaño, alineación) en el widget. ✔️
- Actualización de widgets por intervalo y al configurar. ✔️
- Editor visual interno para scripts, con selector de iconos. ✔️
- Actividad de configuración para seleccionar script al añadir widget (mostrando iconos y colores). ✔️
- Funcionalidades básicas de gestión de scripts (crear, listar, editar [incluyendo selección de icono], renombrar, borrar). ✔️
- Permisos de internet y almacenamiento. ✔️
- Acceso a APIs Java limitadas desde JS (URL, JSONObject). ✔️
- Visualización de iconos personalizados en las listas de scripts. ✔️
- Mejoras en el Editor:
- Resaltado de sintaxis más avanzado y específico para el contexto JSWidgets.
- Sugerencias/autocompletado para APIs expuestas.
- Preview en tiempo real del widget dentro del editor.
- Expansión del API JS:
- Acceso a más información del dispositivo (ej. nivel de batería, estado de red, info de calendario básica).
- Funciones de utilidad (ej. formateo de fechas/horas).
- (Considerar) API para mostrar imágenes simples o iconos en el widget.
- Mejoras en UI/UX de la App Principal:
- Implementar funcionalidad de búsqueda de scripts.
- Interfaz para gestionar ajustes de la app (ej. carpeta de scripts por defecto).
- Posibilidad de duplicar scripts.
- Importación explícita de archivos
.jsdesde el explorador de archivos.
- Mejoras en Widgets:
- Renderizado más rico (si es posible sin afectar demasiado el rendimiento/batería).
- Mejor feedback de errores directamente en el widget.
- Interacción con el widget (ej.
onTappara abrir una URL o refrescar).
- Estabilidad y Rendimiento:
- Optimización de la ejecución de Rhino.
- Manejo robusto de errores y excepciones en scripts y en la app.
- Galería/Repositorio de scripts (online o curado).
- Compartir scripts entre usuarios.
- Disparadores de actualización de widgets más avanzados (ej. por evento del sistema, ubicación).
- Soporte para múltiples tamaños de widgets o layouts dinámicos.
- (Evaluar) Alternativas a Rhino si se encuentran limitaciones significativas (ej. QuickJS, Duktape).
- Seguridad: Fortalecer la sandbox de ejecución de scripts. Validación y saneamiento de lo que los scripts pueden hacer.
- Internacionalización (i18n) y Localización (l10n) de la aplicación.
- Backup y Restauración de scripts (local o en la nube).
- Documentación exhaustiva para desarrolladores de scripts (API disponible, ejemplos, buenas prácticas).
- Monetización: Si el proyecto crece, explorar opciones (ej. versión Pro con características avanzadas, galería premium de scripts).
- Abrir la App: El usuario abre JSWidgets. Se muestra la
MainActivitycon una lista de sus scripts y los ejemplos. - Crear Script:
- El usuario pulsa el icono "+" en la
TopAppBar. - Se navega a
WidgetEditorScreenpara un nuevo script. - El usuario introduce el nombre y el código JavaScript.
- Pulsa "GUARDAR". El script se guarda en el almacenamiento y se actualiza la lista.
- El usuario pulsa el icono "+" en la
- Editar Script:
- En la lista, el usuario pulsa sobre un script o selecciona "Editar" en su menú contextual.
- Se navega a
WidgetEditorScreencon los datos del script cargados. - Modifica el nombre o el contenido.
- Pulsa "GUARDAR".
- Renombrar/Borrar Script:
- El usuario usa las opciones "Renombrar" o "Borrar" del menú contextual de un script.
- Aparecen diálogos de confirmación/entrada. La acción se refleja en el almacenamiento y en la UI.
- Añadir Widget al Homescreen:
- El usuario realiza una pulsación larga en su homescreen y selecciona "Widgets".
- Busca y selecciona el widget de "JSWidgets".
- Se lanza
WidgetConfigActivity, mostrando la lista de todos los scripts disponibles. - El usuario selecciona el script que desea asociar a esta instancia del widget.
- El widget se añade al homescreen y ejecuta el script seleccionado para mostrar su contenido inicial.
- Actualización del Widget:
- El widget se actualiza automáticamente según el
refreshInterval(o el valor por defecto de Android) o cuando su configuración cambia. - Los cambios en un script desde la app principal se reflejarán en las instancias de widget asociadas en su próximo ciclo de actualización.
- El widget se actualiza automáticamente según el
Este documento sirve como una guía viva para el desarrollo de JSWidgets. Se actualizará a medida que el proyecto evolucione.