Я создал PeerSplit — бесплатную одноранговую альтернативу Splitwise — всего за две недели, от идеи до запуска!
PeerSplit — это локальное приложение для разделения групповых расходов. Он работает в автономном режиме, на 100 % бесплатен и конфиденциальен, не требует регистрации или каких-либо личных данных.
Вот как я его построил и все, чему научился на этом пути.
Я уже много лет использую Splitwise для управления расходами с друзьями и соседями по комнате. Но из-за недавних ограничений на ежедневные транзакции и навязчивой рекламы пользоваться им стало неприятно.
Мне нужна была бесплатная альтернатива, обеспечивающая конфиденциальность и не требующая серверов для хранения или синхронизации данных. Я бы не стал доверять свои расходы стороннему серверу.
После работы над одноранговыми локальными проектами, такими как трекер тренировок и приложение для письма, не отвлекающее внимание, я понял, что могу применить тот же подход к разделению расходов.
Так родился PeerSplit. Я начал разрабатывать приложение.
Я плох в проектировании интерфейсов.
Несколько месяцев назад я бы и подумать не мог, что смогу создать такой же совершенный пользовательский интерфейс, как у PeerSplit (некоторые даже говорят, что UX у него лучше, чем у Splitwise).
Итак, как мне это удалось? Nuxt UI.
Пользовательский интерфейс Nuxt великолепен и имеет потрясающий опыт разработки (DX).
Он также поставляется с другими полезными модулями Nuxt, такими как @nuxt/icon, @nuxtjs/tailwindcss и @nuxtjs/colormode.
Все, что мне нужно было сделать, это выбрать основной цвет, и у меня были все необходимые компоненты — значки, темный режим и все остальное — чтобы объединить пользовательский интерфейс PeerSplit.
Для локального хранения и синхронизации данных я использовал cr-sqlite, который основан на wa-sqlite и использует CRDT (бесконфликтные реплицируемые типы данных).
CRDT отлично подходят для одноранговых систем, поскольку они автоматически разрешают конфликты, поэтому пользователи могут работать в автономном режиме, а при повторном подключении изменения плавно сливаются.
Однако cr-sqlite не синхронизирует изменения по сети самостоятельно. Он предоставляет только API для экспорта и объединения изменений. Вам необходимо вручную отправить эти изменения между устройствами.
Для обеспечения безопасной одноранговой синхронизации я использовал Gun.js, который предоставляет одноранговую базу данных с распределенными графами.
API Gun.user от Gun позволяет мне создавать зашифрованные узлы для каждой группы. Все изменения группы хранятся на этом узле и синхронизируются только с участниками группы, сохраняя конфиденциальность.
Когда пользователь выполняет действие, я беру изменения, экспортированные из cr-sqlite, и отправляю их на узел. Когда пользователь снова подключается к сети, Gun синхронизирует новые изменения, сохраняя всех в курсе событий.
Реализовать это эффективно было непросто. Для получения более подробной информации вы можете просмотреть исходный код здесь.
Одной интересной особенностью Splitwise (а теперь и PeerSplit) является «упрощение долгов».
Вот как это работает: если A должен B, а B должен C, A может просто заплатить C напрямую, чтобы потенциально уменьшить количество погашений.
В PeerSplit я сначала рассчитываю чистый баланс для каждого человека. Затем я сортирую эти балансы и предлагаю платежи одну за другой, чтобы каждый раз баланс хотя бы одного человека обнулялся.
Такая сортировка гарантирует, что все увидят на своих устройствах одинаковые выплаты.
Это не на 100% оптимально (в некоторых группах все еще может быть до n-1 платежей), но в большинстве случаев это работает хорошо.
Оптимальное решение требует экспоненциального расчета и позволит сэкономить лишь несколько платежей. Так что это был лучший компромисс между простотой и скоростью!
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; };
Я хотел, чтобы PeerSplit функционировал как автономное приложение, но мне не хотелось сталкиваться с хлопотами по созданию нескольких собственных приложений или длительным процессом их публикации в магазинах приложений. Таким образом, выбор в пользу Progressive Web App (PWA) был очевидным выбором.
PWA сочетает в себе лучшее из веб-приложений и мобильных приложений, позволяя пользователям устанавливать его на свои устройства, сохраняя при этом возможности автономной работы.
Чтобы превратить мое приложение Nuxt в PWA, я использовал vite-pwa.
Я разработал логотип SVG в Figma и использовал его для создания всех необходимых ресурсов PWA с помощью генератора ресурсов vite-pwa.
После этого я настроил манифест PWA, и vite-pwa автоматически настроил для меня сервис-воркера.
Я настроил Nuxt для предварительной обработки всех маршрутов, чтобы мое приложение могло полностью работать в автономном режиме.
И это все. Спасибо за прочтение!
PeerSplit только что запущен на Product Hunt! Это мой первый запуск, и мне бы хотелось вашей поддержки и отзывов.
Посетите PeerSplit на Product Hunt
PeerSplit — это честный исходный код, поэтому не стесняйтесь вносить свой вклад или отправлять запросы на добавление функций на GitHub.
PeerSplit — это бесплатное локальное одноранговое приложение, которое поможет вам легко и конфиденциально разделить и отслеживать групповые расходы.
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3