Construí PeerSplit, una alternativa gratuita de igual a igual a Splitwise, en solo dos semanas, desde la idea hasta el lanzamiento.
PeerSplit es una aplicación local para dividir los gastos del grupo. Funciona sin conexión, es 100% gratuito y privado, y no requiere registros ni ningún dato personal.
Así es como lo construí y todo lo que aprendí a lo largo del camino.
He confiado en Splitwise durante años para gestionar los gastos con amigos y compañeros de cuarto. Pero con sus recientes límites de transacciones diarias y anuncios intrusivos, su uso se ha vuelto frustrante.
Quería una alternativa gratuita que priorizara la privacidad y que no requiriera servidores para almacenar o sincronizar datos. No confiaría mis gastos a un servidor de terceros.
Después de trabajar en proyectos locales entre pares, como un rastreador de ejercicios y una aplicación de escritura sin distracciones, me di cuenta de que podía aplicar el mismo enfoque a la división de gastos.
Así nació PeerSplit. Empecé a diseñar la aplicación.
Soy pésimo diseñando interfaces de usuario.
Hace unos meses, no habría pensado que podría crear una interfaz de usuario tan pulida como la de PeerSplit (algunas personas incluso dicen que tiene una mejor experiencia de usuario que Splitwise).
Entonces, ¿cómo logré hacerlo? Interfaz de usuario de Nuxt.
La interfaz de usuario de Nuxt es magnífica y tiene una experiencia de desarrollador increíble (DX).
También viene con otros módulos útiles de Nuxt como @nuxt/icon, @nuxtjs/tailwindcss y @nuxtjs/colormode.
Todo lo que tenía que hacer era elegir un color primario y tenía todos los componentes que necesitaba (íconos, modo oscuro y todo lo demás) para unir la interfaz de usuario de PeerSplit.
Para el almacenamiento y sincronización de datos locales, elegí cr-sqlite, que se basa en wa-sqlite y utiliza CRDT (tipos de datos replicados sin conflictos).
Los CRDT son excelentes para sistemas peer-to-peer porque manejan los conflictos automáticamente, de modo que los usuarios pueden trabajar sin conexión y, cuando se vuelven a conectar, los cambios se fusionan sin problemas.
Sin embargo, cr-sqlite no sincroniza los cambios a través de la red por sí solo. Solo proporciona API para exportar y fusionar cambios. Debes enviar manualmente esos cambios entre dispositivos.
Para manejar la sincronización segura de igual a igual, utilicé Gun.js, que proporciona una base de datos gráfica distribuida de igual a igual.
La API gun.user de Gun me permite crear nodos cifrados para cada grupo. Todos los cambios de un grupo se almacenan en ese nodo y se sincronizan solo con los miembros del grupo, manteniendo todo privado.
Cuando un usuario realiza una acción, tomo los cambios exportados desde cr-sqlite y los envío al nodo. Cuando el usuario vuelve a conectarse, Gun sincroniza los nuevos cambios y mantiene a todos actualizados.
Implementar esto de manera eficaz fue complicado. Para obtener más detalles, puede consultar el código fuente aquí.
Una característica interesante de Splitwise (y ahora de PeerSplit) es "simplificar las deudas".
Así es como funciona: si A le debe a B y B le debe a C, A puede simplemente pagarle a C directamente para reducir potencialmente el número de pagos.
En PeerSplit, primero calculo el saldo neto de cada persona. Luego clasifico esos saldos y sugiero pagos uno por uno para que el saldo de al menos una persona llegue a cero cada vez.
Esta clasificación garantiza que todos vean los mismos pagos en sus dispositivos.
No es 100% óptimo (algunos grupos aún pueden tener hasta n-1 pagos), pero funciona bien en la mayoría de los casos.
Una solución óptima sería exponencial de calcular y solo ahorraría unos pocos pagos. ¡Así que esta fue la mejor compensación entre simplicidad y velocidad!
export const groupGetPayments = (group) => { const payments = []; const balances = Object.entries(groupGetBalances(group)).map(([a, b]) => [ b, a, ]); balances.sort(); let i = 0, j = balances.length - 1; while (i balances[j][0]) { payments.push({ from: balances[i][1], to: balances[j][1], value: round(balances[j][0]), }); balances[i][0] = balances[j][0]; balances[j][0] = 0; } else { payments.push({ from: balances[i][1], to: balances[j][1], value: round(-balances[i][0]), }); balances[j][0] = balances[i][0]; balances[i][0] = 0; } } return payments; };
Quería que PeerSplit funcionara como una aplicación fuera de línea, pero no quería pasar por la molestia de crear múltiples aplicaciones nativas o lidiar con el largo proceso de publicarlas en las tiendas de aplicaciones. Entonces, optar por una aplicación web progresiva (PWA) fue la elección clara.
Una PWA combina lo mejor de las aplicaciones web y móviles, lo que permite a los usuarios instalarla en sus dispositivos mientras siguen disfrutando de las capacidades sin conexión.
Para transformar mi aplicación Nuxt en una PWA, usé vite-pwa.
Diseñé un logotipo SVG en Figma y lo usé para generar todos los activos PWA necesarios a través del generador de activos de vite-pwa.
Después de eso, configuré el manifiesto de PWA y vite-pwa configuró automáticamente el trabajador del servicio.
Configuré Nuxt para prerenderizar todas las rutas, de modo que mi aplicación pudiera funcionar completamente sin conexión.
Y eso es todo. ¡Gracias por leer!
¡PeerSplit acaba de lanzarse en Product Hunt! Es mi primer lanzamiento y me encantaría contar con su apoyo y comentarios.
Consulte PeerSplit en Product Hunt
PeerSplit es de fuente justa, así que no dudes en contribuir o enviar solicitudes de funciones en GitHub.
PeerSplit es una aplicación gratuita, local y de igual a igual que te ayuda a dividir y realizar un seguimiento de los gastos del grupo de forma fácil y privada.
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3